精讲enable_shared_from_this

1.为什么需要enable_shared_from_this

enable_shared_from_this是为了解决调用shared_ptr构造函数时无法通过原指针(被管理的对象)增加共享指针的统一引用计数(两个非共享的shared_ptr指向同一个对象,未增加引用计数导对象被析构两次)。至于它的具体实现后文再说。
有如下一个资源类

class Obj {
	int id_;
public:
	Obj(int id):id_(id) {
		cout << "创建了一个Obj对象:"<<id_<<endl;
	}
	~Obj() {
		cout << "析构了Obj对象:"<<id_<<endl;
	}

	shared_ptr<Obj> getPtr() {
		shared_ptr<Obj> res = std::move(shared_ptr<Obj>(this));
		cout <<"getPtr中shared_ptr的引用计数:"<< res.use_count() << endl;
		return res;
	}
};

我们用shared_ptr管理它生成的对象,这个资源类的成员函数getPtr的作用是返回当前对象的shared_ptr。然后我们执行下面的测试程序。

void test_shared_from_this() {
	cout << "1..............." << endl;
	shared_ptr<Obj> obj1(new Obj(1));
	cout << "2..............." << endl;
	shared_ptr<Obj> obj2 = obj1->getPtr();
	cout << "3..............." << endl;
	cout << "obj1的引用计数个数:"<< obj1.use_count() << endl;
	cout << "obj2的引用计数个数:"<< obj2.use_count() << endl;
}

得到的结果为:

1...............
创建了一个Obj对象:1
2...............
getPtr中shared_ptr的引用计数:1
3...............
obj1的引用计数个数:1
obj2的引用计数个数:1
析构了Obj对象:1
析构了Obj对象:-572662307

注:在vs2017中是触发了一个异常断点,实际上是重复释放了内存。
从结果可知,创建了一个对象,却析构了两次。为什么会这样?
通过shared_ptr<Obj> obj1(new Obj(1)); 创建了一个id=1的Obj对象,并用智能指针obj1管理它(通过智能指针的构造函数实现),此时obj1中的引用计数为1;然后想通过该对象的getPtr成员函数返回一个智能指针赋值给obj2,在shared_ptr<Obj> res = std::move(shared_ptr<Obj>(this)); 中,我们还是通过构造函数的方式来产生智能指针,因为智能指针的构造函数是不共享引用计数的,所以此时obj2中的引用计数还是1,但是obj1和obj2管理的确是同一个Obj对象,这就导致在函数退出时,该Obj对象被析构了两次。如果将shared_ptr<Obj> obj2 = obj1->getPtr();改为调用拷贝构造函数,也即shared_ptr<Obj> obj2(obj1);,则有

1...............
创建了一个Obj对象:1
2...............
3...............
obj1的引用计数个数:2
obj2的引用计数个数:2
析构了Obj对象:1

此时虽然正确了,但是没有实现要求的getPtr的功能。此时就需要enable_shared_from_this了。

通过继承enable_shared_from_this后,调用该模板类的成员函数share_from_this,就可以实现getPtr的功能。此时代码为

class Obj:public enable_shared_from_this<Obj> {
	int id_;
public:
	Obj(int id):id_(id) {
		cout << "创建了一个Obj对象:"<<id_<<endl;
	}
	~Obj() {
		cout << "析构了Obj对象:"<<id_<<endl;
	}

	shared_ptr<Obj> getPtr() {
		/*shared_ptr<Obj> res = std::move(shared_ptr<Obj>(this));
		cout <<"getPtr中shared_ptr的引用计数:"<< res.use_count() << endl;
		return res;*/
		return shared_from_this();
	}
};

结果为:

1...............
创建了一个Obj对象:1
2...............
3...............
obj1的引用计数个数:2
obj2的引用计数个数:2
析构了Obj对象:1

2.enable_shared_from_this模板类的实现

enable_shared_from_this中包含一个mutable weak_ptr<T> Wptr_;成员变量,继承enable_shared_from_this也就继承了该变量,当第一次构造智能指针时shared_ptr<Obj> obj1(new Obj(1)); 就会初始化Wptr_来指向new出来的对象。再通过share_from_this()代替shared_ptr的普通构造函数返回一个shared_ptr对象,避免产生额外的引用计数器,share_from_this就是通过t提升Wptr_来返回一个shared_ptr

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值