一、std::enable_shared_from_this<T>应用场景
在记录std::enable_shared_from_this之前,需要先看一下原始指针与shared_ptr在使用过程中一些问题。
先看一代码段:
#include <QCoreApplication>
#include <memory>
#include <iostream>
#include <memory>
class Point;
typedef std::shared_ptr<Point> ptr_point;
class Point
{
public:
Point(int _x, int _y) : x(_x), y(_y) {
}
~Point() {
std::cout << "~Point()" << std::endl;
}
ptr_point get_this() {
return ptr_point(this);
}
private:
int x;
int y;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
{
Point *raw_pointer = new Point(8, 9);
std::shared_ptr<Point> ptr(raw_pointer); //[line 1]
std::shared_ptr<Point> ptr2(raw_pointer); //[line 2]
}
return a.exec();
}
上边代码[line 1] [line 2] 是使用原始指针(raw pointer)来创建了两个shared_ptr对象,这样做会造成一个严重问题那就是那一资源会被free两次。为啥会这样?如下图可以看看内存情况:ptr与ptr2指向同一资源(0x3ab8e0),但是两shared_ptr的引用计数器不是同一个,意味着同一资源要被释放两次,这绝对是严重错误。
但是我们确实有这样一种应用场景:就如类Point被shared_ptr管理。且在该类的某成员函数中要把当前类对象作为参数传递给其他函数时,但又要避免上述问题出现。我们就可以使用std::enable_shared_from_this<T>。
二、std::enable_shared_from_this<T>使用方式
1>让类A继承std::enable_shared_from_this<T>,同时将该类类名作为模板参数;
2> 在类成员函数中使用shared_from_this()进行传递该类对象;
更改上边代码并观察内存情况:
#include <QCoreApplication>
#include <memory>
#include <iostream>
#include <memory>
class Point;
typedef std::shared_ptr<Point> ptr_point;
class Point : public std::enable_shared_from_this<Point>
{
public:
Point(int _x, int _y) : x(_x), y(_y) {
}
~Point() {
std::cout << "~Point()" << std::endl;
}
ptr_point get_this() {
return shared_from_this();
}
private:
int x;
int y;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
{
Point *raw_pointer = new Point(8, 9);
std::shared_ptr<Point> ptr(raw_pointer);
std::shared_ptr<Point> ptr2(ptr->get_this());
}
return a.exec();
}
此时内存情况:
这样被释放两次的问题得到解决。相信为啥要使用std::enable_shared_from_this<T>已经讲解清晰。对于其原理可以以后进行陈述。