C++ shared_ptr使用场景和陷阱

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就可以了.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值