C++11 中推出了三种智能指针,unique_ptr、shared_ptr 和 weak_ptr,同时也将 auto_ptr 置为废弃 (deprecated)。
但是在实际的使用过程中,很多人都会有这样的问题:
- 不知道三种智能指针的具体使用场景
-
无脑只使用 shared_ptr
-
认为应该禁用 raw pointer(裸指针,即 Widget * 这种形式),全部使用智能指针
本文将从这几方面讲解智能指针:
- 智能指针的应用场景分析
- 智能指针的性能分析: 为什么 shared_ptr 性能比 unique_ptr 差
- 指针作为函数参数时应该传,传值、传引用,还是裸指针?
首先需要理清楚的概念就是对象所有权的概念。所有权在 rust 语言中非常严格,写 rust 的时候必须要清楚自己创建的每个对象的所有权。
但是 C++ 比较自由,似乎我们不需要明白对象的所有权,写的代码也能正常运行。但是明白了对象所有权,我们才可以正确管理好对象生命周期和内存问题。
C++ 引入了智能指针,也是为了更好的描述对象所有权,简化内存管理,从而大大减少我们 C++ 内存管理方面的犯错机会。
2 std::unique_ptr 专属所有权我们大多数场景下用到的应该都是 unique_ptr。
unique_ptr 代表的是专属所有权,即由 unique_ptr 管理的内存,只能被一个对象持有。 所以,unique_ptr 不支持复制和赋值,如下:
auto w = std::make_unique();
auto w2 = w; // 编译错误
C++
Copy
如果想要把 w 复制给 w2, 是不可以的。因为复制从语义上来说,两个对象将共享同一块内存。
因此,unique_ptr 只支持移动, 即如下:
auto w = std::make_unique();
auto w2 = std::move(w); // w2 获得内存所有权,w 此时等于 nullptr
C++
Copy
unique_ptr 代表的是专属所有权,如果想要把一个 unique_ptr 的内存交给另外一个 unique_ptr 对象管理。只能使用 std::move 转移当前对象的所有权。转移之后,当前对象不再持有此内存,新的对象将获得专属所有权。
如上代码中,将 w 对象的所有权转移给 w2 后,w 此时等于 nullptr,而 w2 获得了专属所有权。
2.1 性能因为 C++ 的 zero cost abstraction 的特点,unique_ptr 在默认情况下和裸指针的大小是一样的。 所以 内存上没有任何的额外消耗,性能是最优的
2.2 使用场景1:忘记deleteunique_ptr 一个最简单的使用场景是用于类属性。代码如下:
class Box{
public:
Box() : w(new Widget())
{}
~Box()
{
// 忘记 delete w
}
private:
Widget* w;
};
C++
Copy
如果因为一些原因,w 必须建立在堆上。如果用裸指针管理 w,那么需要在析构函数中 delete w
; 这种写法虽然没什么问题,但是容易漏写 delete 语句,造成内存泄漏。
如果按照 unique_ptr 的写法,不用在析构函数手动 delete 属性,当对象析构时,属性 w
将会自动释放内存。
假如我们在一段代码中,需要创建一个对象,处理一些事情后返回,返回之前将对象销毁,如下所示:
void process()
{
Widget* w = new Widget();
w->do_something(); // 可能会发生异常
delete w;
}
C++
Copy
在正常流程下,我们会在函数末尾 delete 创建的对象 w,正常调用析构函数,释放内存。
但是如果 w->do_something()
发生了异常,那么 delete w
将不会被执行。此时就会发生 内存泄漏。 我们当然可以使用 try…catch
捕捉异常,在 catch
里面执行 delete
,但是这样代码上并不美观,也容易漏写。
如果我们用 std::unique_ptr,那么这个问题就迎刃而解了。无论代码怎么抛异常,在 unique_ptr 离开函数作用域的时候,内存就将会自动释放。
2.4 使用场景3:STL容器可将 unique_ptr 存储到 STL 容器中,只要对容器元素不使用拷贝操作的算法即可(如 sort())。例如,可在程序中使用类似于下面的代码段
unique_ptr make_int(int n) { return unique_ptr(new int(n)); }
void show(unique_ptr& p1) { cout
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?