shared_from_this的使用

当你想使用一个类的某个成员函数返回指向这个类的指针的时候,可以这样写

class A
{
public:
	A(int y=0):x(y){ }
	A* getthis()
	{
		return this;
	}
	int x;
};
int main (void) 
{
	A a;
	cout<<a.x<<endl;
	A*p=a.getthis();
	p->x=1;
	cout<<a.x<<endl;
}

通过在成员函数中返回this指针,我们得到了指向这个对象本身的指针,并且可以通过它来改变对象。

但是在很多情况中,我们更想用智能指针去控制对象的生存周期,比如这样。

int main (void) 
{
	shared_ptr<A>sp1(new A());
	shared_ptr<A>sp2(sp1->getthis());
	cout<<sp1.use_count()<<endl;
	cout<<sp2.use_count()<<endl;
}

两个智能指针的引用计数都是1,可想而知在函数退出的时候会发生什么,同一块内存被释放了两次,程序崩溃是免不了的。原因是this是裸指针,我们这么操作和用同一个裸指针给两个智能指针赋值是一个意思。如果我们能返回一个智能指针,那么问题就解决了。这时我们可以使用shared_from_this这个模版类。

class A:public enable_shared_from_this<A>
{
public:
	A(int y=0):x(y){ }
	shared_ptr<A> getthis()
	{
		return shared_from_this();
	}
	int x;
};

这样上面那段程序的输出是两个2,两个智能指针都意识到自己指向的是同一片内存,引用计数正确的发挥作用,同一片内存只会被析构一次。

除此之外,shared_from_this还有一个需要注意的地方。你可以点开shared_from_this的源码看看,他返回了enable_shared_from_this中唯一的一个成员变量 

mutable weak_ptr<_Ty> _Wptr; 

而当我们再看这个类的构造函数,并没有对这个成员变量赋值。可想而知,如果这个变量始终没有被赋值,那么我们无法使用shared_from_this这个函数。

为了弄清楚这个变量什么时候被赋值,我一步一步的调试了下面这行代码,虽说只有一行,但是他真的做了很多事情。

shared_ptr<A>sp1(new A());

来看这条语句,它做了三件事情,第一件事情是构造enable_shared_from_this这个类,毕竟想要构造A就要先构造他的父类。

此时wptr没有被赋值。

第二件事情是构造A,此时wptr也没有被赋值。

第三件事情,构造sp1,令人想不到的是,构造sp1之后,属于类A的父类的wptr被赋值了,整个过程跳来跳去说实话我也没看懂,反正是构造sp1之后,wptr才有了值。

所以可想而知,如果没有这样一个sp1的出现,我们是无法使用shared_from_this的。所以才有了所说的“不能再构造函数中调用shared_from_this()”的说法,这个构造函数指的是A的构造函数,因为那个时候wptr还没有值,当然不能调用shared_from_this。

当然了,这样也是不行的。

int main (void) 
{
	A a;
	shared_ptr<A>sp(a.shared_from_this());
}

另外,在同一个继承体系中,不能同时出现多个enable_shared_from_this类。父类继承了enable之后,子类只能对shared_from_this()的返回值进行转型。也就是说把shared_ptr<A>转换成shared_ptr<B>,想做到这一点,你只能这么写

 return dynamic_pointer_cast<B>(shared_from_this());

猜你喜欢

转载自blog.csdn.net/qq_33113661/article/details/89019991