最近在复习C++的一些相关知识,正好把智能指针重新梳理一遍。
智能指针
作用
为什么需要智能指针?说白了就是为了更加“方便智能”的管理内存,当使用原始指针有时候会因为忘记释放内存,从而导致内存泄漏
。智能指针则可以帮我们释放new出来的内存。
1.auto_ptr
auto_ptr 是通过由 new 表达式获得的对象,并在 auto_ptr 自身被销毁时删除该对象的智能指针。
它可用于为动态分配的对象提供异常安全、传递动态分配对象的所有权给函数和从函数返回动态分配的对象。复制 auto_ptr ,会复制指针并转移所有权给目标: auto_ptr 的复制构造和复制赋值都会修改其右侧参数,
而且“副本”不等于原值。因为这些不常见的复制语义,不可将 auto_ptr 置于标准容器中。
此用途及其他使用更适合用 std::unique_ptr 。 (C++11 起)
示例
#include <iostream>
#include <memory>
using namespace std;class Test {int a;
public:Test() : a(0) {cout << "a = 0" << endl;}//explicit Test(int i) : a(i) {cout << "int";}Test(int i) : a(i) {cout << "a:"<< a << endl;}Test(short s) : a(s) {cout << "short";}Test &operator=(int n) {a = n; cout << "operator=";}~Test(){cout << "析构" << endl;}
};int main() {auto_ptr<Test> t(new Test(5));auto_ptr<Test> t1(new Test);//auto_ptr<int []> t2(new int[5]); //不支持(2)unique_ptr<int []> t3(new int[5]);cout << t.get() << endl;cout << t1.get() << endl;t = t1; //(1) ,建议不要这样使用cout << t.get() << endl;cout << t1.get() << endl; return 0;
}
现在一般不使用auto_ptr<>,主要其存在诸多弊端:
1.复制或者赋值都会改变资源的所有权 ,见代码(1)
2.在STL容器中使用auto_ptr存在着重大风险,因为容器内的元素必须支持可复制和可赋值,原因可参考(1)
3.不支持对象数据内存管理,见(2)
所以,C++11用更严谨的unique_ptr 取代了auto_ptr。
unique_ptr
1.基于排他所有权模式:两个指针不能指向同一个资源
2.无法进行左值unique_ptr复制构造,也无法进行左值复制赋值操作,但允许临时右值赋值构造和赋值
3.保存指向某个对象的指针,当它本身离开作用域时会自动释放它指向的对象。
4.在容器中保存指针是安全的
unique_ptr<Test> t(new Test(5));unique_ptr<Test> t1(new Test);cout << "---------------" << endl;//t = t1; //不支持,两个指针不能指向同一资源//unique_ptr<Test> t2(t1);//不支持,可以理解为不能指向同一资源unique_ptr<Test> t3(move(t1));//允许,移动了所有权,将t1的所有权给了t3
shared_ptr
std::shared_ptr 是通过指针保持对象共享所有权的智能指针。多个 shared_ptr 对象可占有同一对象。
下列情况之一出现时销毁对象并解分配其内存:
1.最后剩下的占有对象的 shared_ptr 被销毁;
2.最后剩下的占有对象的 shared_ptr 被通过 operator= 或 reset() 赋值为另一指针。
这就是共享模式,他很好的解决了unique_ptr<>的缺点,使得多个指针能够指向同一个资源。
shared_ptr<Test> t(new Test(5));shared_ptr<Test> t1(new Test());cout << t.use_count() << endl; //引用计数cout << t.unique() << endl;//判断当前是否仅有一个指针进行管理cout << t1.use_count() << endl;t1 = t;cout << "t1 = t" << endl;cout << t1.use_count() << endl; // t1 和 t两个指针进行管理cout << t.use_count() << endl;cout << t.unique() << endl;cout << "-------------------" << endl;
智能指针常用方法
1.reset
替换所管理的对象
(公开成员函数)
2.swap
交换所管理的对象
(公开成员函数)
3.get
返回存储的指针
(公开成员函数)
4.use_count
返回 shared_ptr 所指对象的引用计数
(公开成员函数)
5.unique
(C++20 前)
检查所管理对象是否仅由当前 shared_ptr 的实例管理
4和5为共享指针所有