C++11标准库提供了两种智能指针(smart pointer)类型来管理动态对象。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指的对象。C++11标准库提供的这两种智能指针的区别在于管理底层指针的方式:shared_ptr允许多个指针指向同一个对象;unique_ptr则"独占"所指向的对象。C++11标准库还定义了一个名为weak_ptr的辅助类,它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。智能指针是模板类而不是指针。类似vector,智能指针也是模板,当创建一个智能指针时,必须提供额外的信息即指针可以指向的类型。默认初始化的智能指针中保存着一个空指针。智能指针的使用方式与普通指针类似。解引用一个智能指针返回它指向的对象。如果在一个条件判断中使用智能指针,效果就是检测它是否为空。
1、shared_ptr智能指针内存管理的思路
shared_ptr智能指针的解决思路:最后一个引用它的对象被释放时,释放这段内存。
实现方法:对 被管理的资源 进行计数。当一个sharedptr对象要共享这个资源的时候,该资源的引用计数加1,当该对象生命周期结束了,再把该引用计数减1。这样,当最后一个引用它的对象被释放的时候,资源的引用计数减少到0,此时释放该资源。
智能指针最终的实现是 两个指针成员:一个指向数据成员,一个指向计数器成员
智能指针里的计数器 维护的是一个指针,指向的 实际内存 在堆上,不是栈上的
make_shared类似于emplace_back()它是一种更好且更安全的方法:因为使用new时会创建一个对象,计算它的引用计数时会创建一个对象,而make_shared只会创建一个对象,并且不会出现控制模块失效的情况。make_shared返回指向此对象的shared_ptr
2、weak_ptr
weak_ptr<T>w
weak_ptr<T>w(sp)
w = p p可以是一个shared_ptr或一个weak_ptr赋值后wp共享对象
w.reset() 将w置空
w.use_count() 与w共享的shared_ptr的数量
w.expired() 若w.use_count()为0,返回true,否则返回false
w.lock() 若expired为true,返回一个空shared_ptr;否则返回一个指向w的对象的shared_ptr(也就是说对象不为空)
auto p = make_shared<int>(41);
weak_ptr<int> wp(p);
weak_ptr是弱指针,由于是弱共享创建wp不会改变p的引用计数;(相当于一个小弟)wp指向的对象(大哥shared_ptr的对象)
可能 被释放掉。所以不能用weak_ptr直接访问对象,需要使用lock,对象被释放返回一个空shared_ptr,对象不为空返回一个指向w的对象的shared_ptr
3、shared_ptr
shared_ptr<T> p(q)
shared_ptr<T>p(u)
p = q p和q都是shared_ptr,所保存的指针必须能相互交换,此操作会递减p的引用计数,递增q的引用计数,若p的引用计数变为0,则将其管理的原内存释放
p.unique 若p.use_count()为1,返回true,否则返回false
p.use_count()返回与p共享的智能指针数量,可能很慢主要用于调试
4、unique_ptr
unique_ptr没有类似make_shared的标准库函数,必须unique_ptr<int>p(new int(10)),不支持赋值和拷贝
unique_ptr<string>p1(new string("aaa"))
unique_ptr<string>p2(p1);不支持拷贝所以不对(有点类似拷贝构造函数 Complex c2(c1); Complex c2 = c1;//这个是初始化不是赋值)
unique_ptr<string>p3
p3 =p2 不支持赋值所以不对
unique_ptr<string>u;
u = nullptr 释放u指向的对象,将u置空
u.release() u放弃对指针的控制权,返回指针并将u置为空
u.reset() 释放u指向的对象 //释放对象,同时赋空
u.reset(q)如果提供了内置指针q,令u指向这个对象,否则将u置空
unique_ptr<string>不支持普通的拷贝和赋值操作,但是可以通过release or reset来转移所有权。
p2.reset(p3.release())将所有权从p3转移给p2,reset释放了原来的内存或者使用move
auto px = p.release(); //让出指针所有权,但是并没有销毁
delete px; //这里需要手动delete px
#include <iostream>
#include <string>
#include <memory>
using namespace std;
void main()
{
shared_ptr<string>p1(new string("aaa"));
shared_ptr<string>p2 = make_shared<string>(10,'9');
shared_ptr<int>p3 = make_shared<int>();
auto p4 = make_shared<string>(10,'9');
cout << *p1 << endl;
cout << *p2 << endl;
cout << *p3 << endl;
cout << *p4 << endl;
auto q = make_shared<int>(10);
weak_ptr<int> wp(q);//弱共享wp不会改变q的引用计数
cout << "wp.use_count(): " << wp.use_count() << endl;//弱引用计算共享对象shared_ptr的数量
if(!wp.expired())
{
cout << "wp.expire(): " << "false" << endl;
}else{
cout << "wp.expire(): " << "true" << "已删除delete" << endl;//use_count()=0返回true
}
auto ret = wp.lock();
if(ret)
{
cout << "wp.lock(): " << "false" << *ret << endl;//不为空返回一个指向wp对象的shared_ptr
}
unique_ptr<string> p5(new string("uuuuuuuuuu"));
cout << *p5 << endl;
unique_ptr<string> p6(p5.release());
unique_ptr<string> p7(new string("uuuuuuuuuu"));
p6.reset(p7.release());
cout << *p6 << endl;
}