主要看常用的std::shared_ptr std::unique_ptr 比及可构造智能指针的std::make_unique(c++14引入)和std::make_shared.这里设计到完美转发 以及类模板等相关知识。
使用时头文件 #include <memory>
std::shared_ptr 与std::unique_ptr都支持的操作
shared_ptr<T> sq
unique_ptr<T> up
*p解引用
p.get()返回保存的指针
swap(p,q)
p.swap(q)
std::shared_ptr独有
std::shared_ptr = std::make_shared<T>(args)
shared_ptr<T>p(q)
p.unique() 若p.use_count()为1,返回true
p.use_count()返回与p共享的智能指针的数量,慢 主要用于调试
1.初始化
std::shared_ptr<T>(args)
std::shared_ptr<T> (new T(args))
std::shared_ptr<T> = std::make_shared<T>(args)
shared_ptr<string> p1 = make_shared<string>(10, '9');
shared_ptr<string> p2 = make_shared<string>("hello");
shared_ptr<string> p3 = make_shared<string>();
使用make_shared是安全高效的
// (1)
std::shared_ptr<Widget> p1(new Widget);
存在两次内存分配操作:
1.new Widget
2.为p1分配控制块(control block),控制块用于存放引用计数等信息
// (2)
std::shared_ptr<Widget> p2(std::make_shared<Widget>(构造或初始化所用的参数));
只有一次内存内配操作,make_shared会一次性申请足够大的空间用于存放Widget对象和智能指针的控制块。
std::shared_ptr
是通过引用计数的方式来管理自己的生命周期。
引用计数是通过动态分配一个控制块(参考三、关于控制块的几点说明)来实现的。
我们可以想象与std::shared_ptr<T>
对象相关的内存:
std::shared_ptr对于动态数组的情况
std::shared_ptr<int[]> sp1(new int[10]()); // 错误,c++17前不能传递数组类型作为shared_ptr的模板参数
std::unique_ptr<int[]> up1(new int[10]()); // ok, unique_ptr对此做了特化
std::shared_ptr<int> sp2(new int[10]()); // 错误,可以编译,但会产生未定义行为,请不要这么做
std::uniuqe_ptr
某个时刻只能由一个unique_ptr指向一个对象,其被销毁时, 所指向对象也销毁。
最好用c++14才有的std::make_unique来初始化
std::unique_ptr<Foo> pf = std::make_unique<Foo>(10);
std::unique_ptr<int>p1 或 std::unique_ptr<int>p1(new int(42))
因为只指向一个对象,所以不支持拷贝和赋值 如:
std::unique_ptr<int>p2(p1) ;错误
std::unique_ptr<int>p2;错误
p2 = p2
可以通过完美转发std::move完成传递
p2 = change_a(std::move(p1));
p1.release()放弃对指针p1的控制权,返回unique当前保存的指针并将p1置空,也可以用于控制权转移 p2(p1.release())
p1.reset()释放p1指向的对象
p1.reset(p2.release()), p2的指向给了p1, p2置空
下面说下其的作为参数传递和返回