c++ 智能指针
智能指针
- 智能指针式为了解决手动管理动态分配内存的问题,使用RAII(资源获取即初始化)原则,通过在对象的构造函数中分配内存,并在对象的析构函数中释放内存,从而保证资源的正确释放,避免了内存泄漏
std::unique_ptr
- 管理独占所有权的对象指针,保证在其周期结束时释放内存,智能通过移动语义来转移所有权,不能进行复制,通常用于单个所有者的场景,比如管理动态分配的对象或者资源
std::unique_ptr<int> ptr(new int(42));
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
- 这个就是将裸指针进行一个单纯的封装,构造函数和析构函数
std::shared_ptr
- 允许多个指针共享同一个对象,使用引用计数来追踪有多少个指针指向相同的对象,只有当最后一个std::shared_ptr超出作用域时,内存才会被释放,通常用于共享资源所有权的场景
std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
std::shared_ptr<int> ptr2 = ptr1;
- shared_ptr需要维护的信息有两部分
- 指向共享资源的指针
- 引用计数等共享资源的控制信息——事实上是维护一个指向控制信息的指针
std::shared_ptr<T> sptr1(new T);
std::shared_ptr<T> sptr2 = sptr1;
- 这里看着每个shared_ptr对象和控制信息都指向共享资源,但是有的时候不会指向同一个,但是这里不会指向同一个的情况暂时没看懂
std::weak_ptr
- 是对std::shared_ptr的一种扩展,允许观察共享对象但不拥有它,不会增加引用计数,因此不会影响对象的声明周期,但是不能访问所观察的对象
- 主要是和shared_ptr共同使用,但不会增加和减少shared_ptr的引用计数,主要用来获得对应shared_ptr的状态信息
std::shared_ptr<int> sharedPtr = std::make_shared<int>(42);
std::weak_ptr<int> weakPtr = sharedPtr;
- 当shared_ptr析构并释放共享资源的时候,只要weak_ptr对象还存在,控制块就会保留,weak_ptr可以通过控制块观察对象是否存活
循环引用问题
- 智能指针循环引用指的是在使用智能指针时,存在多个智能指针相互引用,形成一个循环的情况,会导致资源无法被正确释放,从而导致内存泄漏
class A;
class B;
class A {
public:
std::shared_ptr<B> bPtr;
~A() {
std::cout << "A destructor called." << std::endl;
}
};
class B {
public:
std::shared_ptr<A> aPtr;
~B() {
std::cout << "B destructor called." << std::endl;
}
};
int main() {
std::shared_ptr<A> pa = std::make_shared<A>();
std::shared_ptr<B> pb = std::make_shared<B>();
pa->bPtr = pb;
pb->aPtr = pa;
return 0;
}
- 此时两个Object的引用计数都是2,例如A的两个引用是pa,pb->ptrA,这里不能说A的两个引用,但是是表示这个意思
- 此时线程结束,pa,pb结束,但是引用计数只是变为了1,此时ptrA,ptrB没有被释放。
- 可以将shared_ptr换成weak_ptr,因为weak_ptr不增加引用计数
- 上述程序什么也不会输出,因为A B还存在引用计数,因此不会调用对应的析构函数
作者:孙建钊
出处:http://www.cnblogs.com/sunjianzhao/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。