C++ STL 四种智能指针

您所在的位置:网站首页 问题空间的四种类型 C++ STL 四种智能指针

C++ STL 四种智能指针

2024-07-11 00:17| 来源: 网络整理| 查看: 265

在这里插入图片描述

文章目录 0.前言1.unique_ptr2.auto_ptr3.shared_ptr3.1 简介3.2 通过辅助类模拟实现 shared_ptr 4.weak_ptr4.1 简介4.2 用法4.3 作用 5.如何选择智能指针参考文献

0.前言

C++ 标准模板库 STL(Standard Template Library)共提供了四种智能指针:

auto_ptrunique_ptrshared_ptrweak_ptr

auto_ptr 是 C++98 提出的,C++11 已将其摒弃,并提出了 unique_ptr 替代 auto_ptr。虽然 auto_ptr 已被摒弃,但在实际项目中仍可使用,但建议使用更加安全的 unique_ptr,后文会详细叙述。

shared_ptr 和 weak_ptr 则是 C+11 从准标准库 Boost 中引入的两种智能指针。

此外,Boost 库还提出了 boost::scoped_ptr、boost::scoped_array、boost::intrusive_ptr 等智能指针,虽然尚未得到 C++ 标准采纳,但是在开发实践中可以使用。

1.unique_ptr

unique_ptr 由 C++11 引入,旨在替代不安全的 auto_ptr。

unique_ptr 是一种定义在头文件中的智能指针。它持有对对象的独有权——两个unique_ptr 不能指向一个对象,即 unique_ptr 不共享它所管理的对象。它无法复制到其他 unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL)算法,只能移动 unique_ptr,即对资源管理权限可以实现转移。这意味着,内存资源所有权可以转移到另一个 unique_ptr,并且原始 unique_ptr 不再拥有此资源。实际使用中,建议将对象限制为由一个所有者拥有,因为多个所有权会使程序逻辑变得复杂。构造 unique_ptr 时,可使用 make_unique 函数。

下图演示了两个 unique_ptr 实例之间的所有权转换。 在这里插入图片描述 unique_ptr 与原始指针一样有效,并可用于 STL 容器。将 unique_ptr 实例添加到 STL 容器运行效率很高,因为通过 unique_ptr 的移动构造函数,不再需要复制操作。

unique_ptr 指针与其所指对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过 reset 方法重新指定、通过 release 方法释放所有权、通过移动语义转移所有权。unique_ptr 还可能未指向任何对象,这种情况被称为空 unique_ptr。

unique_ptr 的基本操作有:

// 创建 // 创建空智能指针 unique_ptr p; unique_ptr p(nullptr) // 创建时指定对象 unique_ptr p(new int(1)); // 销毁旧对象(如果有)然后绑定新对象 p.reset(new int(1)); // 用类型为 D 的对象替代默认删除器 std::default_delete unique_ptr p(new int(1)); unique_ptr p(new int(1), D()); // 所有权变化 // 释放所有权 int *pi = p.release(); // 转移所有权 p2.reset(p1.release()); // 通过移动转移所有权,转移后 p1 变成空指针 unique_ptr p2 = std::move(p1); // 显式销毁所指对象,同时智能指针变为空指针。与 p.reset() 等价 p = nullptr; 2.auto_ptr

auto_ptr 同样是 STL 智能指针家族的成员之一,由 C++98 引入,定义在头文件。其功能和用法类似于 unique_ptr,由 new expression 获得对象,在 auto_ptr 对象销毁时,他所管理的对象也会自动被 delete 掉。

auto_ptr 从 C++98 使用至今,为何从 C++11 开始,引入 unique_ptr 来替代 auto_ptr 呢?原因主要有如下几点:

(1)基于安全考虑。

先来看下面的赋值语句:

auto_ptr ps (new string ("I reigned lonely as a cloud.”); auto_ptr vocation; vocaticn = ps;

上述赋值语句将完成什么工作呢?如果 ps 和 vocation 是常规指针,则两个指针将指向同一个 string 对象。这是不能接受的,因为程序将试图删除同一个对象两次,一次是 ps 过期时,另一次是 vocation 过期时。要避免这种问题,有多种方法。

定义陚值运算符,使之执行深复制。这样两个指针将指向不同的对象,其中的一个对象是另一个对象的副本,缺点是浪费空间,所以智能指针都未采用此方案。建立所有权(ownership)概念。对于特定的对象,只能有一个智能指针可拥有,这样只有拥有对象的智能指针的析构函数会删除该对象。然后让赋值操作转让所有权。这就是用于 auto_ptr 和 unique_ptr 的策略,但 unique_ptr 的策略更严格。创建智能更高的指针,跟踪引用特定对象的智能指针数。这称为引用计数。例如,赋值时,计数将加 1,而指针过期时,计数将减 1,。当减为 0 时才调用 delete。这是 shared_ptr 采用的策略。

当然,同样的策略也适用于复制构造函数,即auto_ptr vocation(ps)时也需要上面的策略。每种方法都有其用途,但为何要摒弃 auto_ptr 呢?

下面举个例子来说明。

#include #include #include using namespace std; int main() { auto_ptr films[5] ={ auto_ptr (new string("Fowl Balls")), auto_ptr (new string("Duck Walks")), auto_ptr (new string("Chicken Runs")), auto_ptr (new string("Turkey Errors")), auto_ptr (new string("Goose Eggs")) }; auto_ptr pwin; // films[2] 将所有权转让给 pwin,此时 films[2] 不再引用该字符串从而变成空指针。 pwin = films[2]; cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3