shared_from_this是基类enable_shared_shared_from_this的一个方法,允许继承类获取一个只想自身的shared_ptr智能指针,这个智能指针与已有的shared_ptr共享所有权。
我们可以查看其源码
/*VS2019*/
template <class _Ty>
class enable_shared_from_this { // provide member functions that create shared_ptr to this
public:
using _Esft_type = enable_shared_from_this;
_NODISCARD shared_ptr<_Ty> shared_from_this() {
return shared_ptr<_Ty>(_Wptr);
}
_NODISCARD shared_ptr<const _Ty> shared_from_this() const {
return shared_ptr<const _Ty>(_Wptr);
}
_NODISCARD weak_ptr<_Ty> weak_from_this() noexcept {
return _Wptr;
}
_NODISCARD weak_ptr<const _Ty> weak_from_this() const noexcept {
return _Wptr;
}
protected:
constexpr enable_shared_from_this() noexcept : _Wptr() {}
enable_shared_from_this(const enable_shared_from_this&) noexcept : _Wptr() {
// construct (must value-initialize _Wptr)
}
enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept { // assign (must not change _Wptr)
return *this;
}
~enable_shared_from_this() = default;
private:
#if _HAS_IF_CONSTEXPR
template <class _Yty>
friend class shared_ptr;
#else // ^^^ _HAS_IF_CONSTEXPR // !_HAS_IF_CONSTEXPR vvv
template <class _Other, class _Yty>
friend void _Enable_shared_from_this1(const shared_ptr<_Other>& _This, _Yty* _Ptr, true_type) noexcept;
#endif // _HAS_IF_CONSTEXPR
mutable weak_ptr<_Ty> _Wptr;
};
具体的使用方法如下
#include<memory>
#include<iostream>
class A : public std::enable_shared_from_this<A>{
public:
A(){
std::cout << "construc A" << std::endl;
}
~A(){
std::cout << "deConstruct A" << std::endl;
}
void fun(){
std::shared_ptr<A> p = shared_from_this();
}
};
int main(){
std::shared_ptr<A> foo, bar;
foo = std::make_shared<A>();
foo->fun();
bar = foo->shared_from_this();
if(!foo.owner_before(bar) && !bar.owner_before(foo)){
std::cout << "foo and bar share ownership" << std::endl;
}
}
/* out
construc A
foo and bar share ownership
deConstruct A
*/
会产生两种错误,一种是产生bad_weak_ptr错误,这类错误编译时正常,运行时报错:
会产生这种错误有两种原因:
1、在派生类的构造函数中调用shared_from_this函数
class B : public std::enable_shared_from_this<B>{
public:
B(){
std::cout << "construc B" << std::endl;
std::shared_ptr p = shared_from_this();
}
~B(){
std::cout << "deConstruct B" << std::endl;
}
};
由于B本身都没有构造完成,此时相当于使用this指针自然就会报错,此时enable_shared_from_this中的weak_ptr还未完成初始化。
2、利用一个裸指针,指向堆(栈)上的对象,没有使用shared_ptr的构造方式,造成enable_shared_from_this中的weak_ptr没有初始化
class C : public std::enable_shared_from_this<C>{
public:
C(){
std::cout << "construc C" << std::endl;
}
~C(){
std::cout << "deConstruct C" << std::endl;
}
void fun(){
std::shared_ptr<C> p = shared_from_this();
}
};
int main(){
C* c = new C();//C* c;
c->fun();
}
第二种错误是继承导致,即在同一个继承体系下只能出现一个enable_shared_from_this父类,在父类已经继承了enable_shared_from_this时,子类需要继续无法继续使用enable_shared_from_this方法,子类只能对父类的shared_from_this的返回值进行类型转换。
#include<memory>
#include<iostream>
class A : public std::enable_shared_from_this<A>{
public:
A(){
std::cout << "construc A" << std::endl;
}
virtual ~A(){
std::cout << "deConstruct A" << std::endl;
}
void fun1(){
auto p = shared_from_this();
}
};
class B : public A{
public:
B(){
std::cout << "construc D" << std::endl;
}
~B(){
std::cout << "deConstruct D" << std::endl;
}
void fun(){
auto p = std::dynamic_pointer_cast<B>(shared_from_this());
}
};
int main(){
std::shared_ptr<B> b = std::make_shared<B>();
b->fun();
}