文章目录
shared_ptr 使用场景
当把shared_ptr当作返回对象, 如果将shared_ptr接住就不会被销毁.
shared_ptr<int> create_shared_ptr(int value)
{
return make_shared<int>(value);
}
shared_ptr<int> func(int value)
{
shared_ptr<int> temp = create_shared_ptr(value);
return temp;
}
auto ptr = func(5); // 使用ptr接住返回值, 对象不会被销毁
shared_ptr使用陷阱分析
慎用裸指针
情况1:
将一个裸指针指向的对象交给智能指针托管之后,避免裸指针后续的使用,否则会导致不可预料的结果
void func(shared_ptr<int> temp)
{
return;
}
```cpp
int* p = new int(100);
func(shared_ptr<int>(p));
*p = 45;
这里的函数参数托管了裸指针的对象, 当跳出了函数的时候,temp过期被销毁,指向的对象也被销毁了.后续在使用裸指针会造成非法访问.
情况2:
不要使用裸指针初始化多个智能指针, 这样会导致每个智能指针的引用计数都没有关联.在内存释放的时候造成内存的多次释放而引发程序崩溃
int* p = new int(100);
shared_ptr<int> p1(p);
shared_ptr<int> p2(p);
在这里p1和p2的引用计数都为1, 没有关联, 每次的释放都会释放同一个对象,造成多次释放, 引发程序的崩溃.
慎用get()返回的裸指针
情况1:
不要将get返回的裸指针delete掉, 否则会导致异常
shared_ptr<int> ptr(new int(100));
int* pi = ptr.get();
delete pi;
情况2:
不能将其他智能指针绑定到get()返回的指针上
shared_ptr<int> ptr1(new int(100));
int* pi = ptr1.get();
{
shared_ptr<int> ptr2(pi);
}
*ptr1 = 98;
在这里ptr2出了作用域,会释放指向的对象,在之后的过程中再次的使用ptr1的时候会造成非法访问.
不要把类对象指针(this)作为shared_str返回,改用enable_shared_from_this
class A
{
public:
shared_ptr<A> get_self() { return shared_ptr<A>(this); }
};
shared_ptr<A> a_1(new A);
shared_ptr<A> a_2 = a_1->get_self();
在这里a_1和a_2分别引用计数, 没有关联, 会造成同一个对象被释放两次,使得程序崩溃.要这样做, 就必须要让两个对象关联起来, 所以介绍一种可行的方法.enable_shared_from_this(c++标准库里面的类模板)
class A : public enable_shared_from_this<A>
{
public:
shared_ptr<A> get_self()
{
// return shared_ptr<A>(this); 会造成崩溃, 改用下面的方法
return shared_from_this();
}
};
shared_ptr<A> a_1(new A);
shared_ptr<A> a_2 = a_1->get_self();
智能指针循环依赖
class B;
class A
{
public:
shared_ptr<B> pb;
~A() { cout << "A拜拜" << endl; }
};
class B
{
public:
shared_ptr<A> pa;
~B() { cout << "A拜拜" << endl; }
};
shared_ptr<A> pa(new A);
shared_ptr<B> pb(new B);
pa->pb = pb;
pb->pa = pa;
在这里a_1指向了A类对象, a_2指向了B类对象, 在他们内部的指针又互相指向对方,这样便造成了循环依赖, 在对象过期的时候, 这里的计数从2变成了1, 没有变成零, 所以导致内存泄漏.
使用weak_ptr解决循环依赖(交叉引用)
class B;
class A
{
public:
weak_ptr<B> pb;
~A() { cout << "A拜拜" << endl; }
};
class B
{
public:
shared_ptr<A> pa;
~B() { cout << "B拜拜" << endl; }
};
shared_ptr<A> pa(new A);
shared_ptr<B> pb(new B);
pa->pb = pb;
pb->pa = pa;
在这里只需要将其中任何一个成员指针改变为weak_ptr就可以了.