头文件memory
智能指针的->运算符重载
不带引用计数的智能指针为什么智能指针要区分带引用计数或不带引用计数呢?
因为多个智能指针指向同一份资源会引起资源的重复释放,即浅拷贝资源释放的问题,所以有的不带引用计数,但是只能有一个智能指针指向该份资源,有的带引用计数
auto_ptrauto_ptr怎么解决浅拷贝资源多份释放的问题?
答:永远让最后一个auto_ptr指向该份资源,前边的auto_ptr被置为nullptr,图示如下:
所以auto有很多缺点:
- 不推荐使用auto_ptr,并且在容器中最好不要用auto_ptr,因为如果容器里都是auto_ptr,如果容器要拷贝,那么之前的容器里的auto_ptr就全被置为nullptr了,说的绝对点就是:auto_ptr 不能被用在 stl 标准容器中
- 因为auto_ptr的所有权独有,所以要防止两个auto_ptr拥有同一个对象
由于auto_ptr的种种弊端,C11舍弃掉了auto_ptr
scoped_ptr(boost库中的)scope怎么解决浅拷贝资源多份释放的问题?
答:scope直接把拷贝构造和赋值 *** 作给删除/禁掉了,也就是语法上不让你多个指针指向同一份堆内存,不让你用一个scoped_ptr去构造另一个scoped_ptr,scope_ptr没有提供带右值引用的拷贝构造
scoped_ptr使用的比较少,不带引用计数的智能指针推荐使用unique_ptr
unique_ptr不带引用计数的智能指针推荐使用unique_ptr
unique_ptr只让一个智能指针管理资源,unique_ptr也禁掉了拷贝构造和赋值,但是提供了带右值引用的拷贝构造和赋值重载,所以涉及到右值的拷贝构造都是可以用unique_ptr的,比如用std::move移动语义将一个指针的资源转移到新指针、作为函数返回值类型,unique_ptr相当于独占资源
unique_ptr<int> p1(new int);
unique_ptr<int> p2(p1); //error
//但是可以这样:
unique_ptr<int> p2(std::move(p1)); //ok
template<typename T>
unique_ptr<T> getSmartPtr()
{
unique_ptr<T> ptr(new T());
return ptr; //ok
}
unique_ptr<int> up = getSmartPtr<int>(); //ok
unique_ptr相比于auto_ptr的好处:
- unique_ptr在写的时候,如果想拷贝构造成功,用户是一定要写std::move的,用意是很明显的(资源转移)
- 而auto_ptr没有禁掉拷贝构造,却底层实现了资源的转移,用户正常使用ptr2(ptr1);,却已经把ptr1的资源转移给ptr2了,就很危险
带引用计数:多个智能指针可以管理同一个资源
带引用计数:给每一个对象资源,匹配一个引用计数
智能指针 =》引用资源的时候 =》引用计数+1
智能指针 =》不使用资源的时候 =》引用计数-1 =》!=0 不释放资源,为0释放资源
库里面的shared_ptr和weak_ptr引用计数的加减是线程安全的,因为用atomic定义了引用计数
shared_ptr是强智能指针,可以改变资源的引用计数
循环引用问题,造成new出来的资源无法释放,资源泄露
class B;
class A
{
public:
A() { cout<<"A()"<<endl; }
~A() { cout<<"~A()"<<endl; }
shared_ptr<B> ptrb;
};
class B
{
public:
B() { cout<<"B()"<<endl; }
~B() { cout<<"~B()"<<endl; }
shared_ptr<A> ptra;
};
int main()
{
shared_ptr<A> pa(new A());
shared_ptr<B> pb(new B());
pa->ptrb = pb;
pb->ptra = pa;
cout<<pa.use_count() <<endl; //打印引用计数
cout<<pb.use_count() <<endl;
}
如何解决循环引用问题?
- 定义对象的时候,用强智能指针;引用对象的地方,使用弱智能指针
- weak_ptr之所以可以打破循环引用,是因为:将一个 weak_ptr 绑定到一个 shared_ptr 不会改变 shared_ptr 的引用计数
weak_ptr是弱智能指针,不会改变资源的引用计数
weak_ptr =》(观察)shared_ptr =>(管理) 资源(内存)
注意:weak_ptr只是一个观察者,它并不能直接 *** 纵资源,没有重载->和*运算符,所以不能->这样输出,要用lock返回shared_ptr类型才能用->
强弱智能指针解决的另一问题:多线程访问共享对象的线程安全问题
自定义删除器智能指针的删除器:deletor,对于不同的资源有不同的资源释放方式
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)