shared_from_this
class只要继承自std::enable_shared_from_this<class>,程序便可以通过shared_from_this获取共享的智能this指针。
使用示例
- 示例1
当获取某个类对象的智能指针时,避免出现两个引用计数独立的智能指针同时指向同一个实例,从而出现double free的问题。
#include <memory>
#include <iostream>
struct Good: std::enable_shared_from_this<Good> // note: public inheritance
{
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
struct Bad
{
std::shared_ptr<Bad> getptr() {
return std::shared_ptr<Bad>(this);
}
~Bad() { std::cout << "Bad::~Bad() called\n"; }
};
int main()
{
// Good: the two shared_ptr's share the same object
std::shared_ptr<Good> gp1 = std::make_shared<Good>();
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';
// Bad: shared_from_this is called without having std::shared_ptr owning the caller
try {
Good not_so_good;
std::shared_ptr<Good> gp1 = not_so_good.getptr();
} catch(std::bad_weak_ptr& e) {
// undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17)
std::cout << e.what() << '\n';
}
// Bad, each shared_ptr thinks it's the only owner of the object
std::shared_ptr<Bad> bp1 = std::make_shared<Bad>();
std::shared_ptr<Bad> bp2 = bp1->getptr();
std::cout << "bp2.use_count() = " << bp2.use_count() << '\n';
} // UB: double-delete of Bad
Possible output:
gp2.use_count() = 2
bad_weak_ptr
bp2.use_count() = 1
Bad::~Bad() called
Bad::~Bad() called
*** glibc detected *** ./test: double free or corruption
- 示例2
lambda表达式利用shared_from_this可以安全的捕获this指针
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <algorithm>
#include <functional>
#include <mutex>
#include <thread>
#include <exception>
#include <Windows.h>
using namespace std;
class Foo : public enable_shared_from_this<Foo>
{
private:
int a = 11;
public:
void func()
{
auto tmp_shared = shared_from_this();
// 如果此处捕获的式this指针,程序结果又会如何?
std::thread([tmp_shared]()
{
Sleep(1000);
cout << "sleep over" << endl;
cout << "a is " << tmp_shared->a << endl;
}).detach();
cout << "func return" << endl;
}
Foo() { cout << "in Foo" << endl; }
~Foo() { cout << "in ~Foo" << endl; }
};
int main()
{
{
auto a = make_shared<Foo>();
a->func();
}
getchar();
return 0;
}