我只知道std::enable_shared_from_this
表格this link
但在阅读下面的代码后,我不知道何时使用它。
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';
}
上面的代码是&#34;不太好&#34;因为在调用shared_ptr
之前没有getptr()
。所以好消息应该是:
std::shared_ptr<Good> gp1 = std::make_shared<Good>(); // having a shared_ptr at the beginning
std::shared_ptr<Good> gp2 = gp1->getptr();
但是,如果我已经拥有shared_ptr
个对象,为什么我不能简单地编码:std::shared_ptr<Good> gp2 = gp1;
,这意味着我不需要std::enable_shared_from_this
总而言之。
在我看来,使用std::enable_shared_from_this
是为了确保多个shared_ptr
个对象具有相同的控制块,以便我们可以避免the double-delete problem。但是,如果我必须提醒自己在开头创建一个shared_ptr
,为什么我不提醒自己使用shared_ptr
对象来创建一个新对象,而不是使用原始指针?
答案 0 :(得分:6)
有关std::enable_shared_from_this<T>
何时有用的提示在其名称中:当根据某些请求产生对象时,可能需要返回指向对象本身的指针。如果结果应该是std::shared_ptr<T>
,则必须从通常没有std::shared_ptr<T>
可访问的成员函数中返回这样的指针。
派生自std::enable_shared_from_this<T>
提供了一种方法来获得std::shared_ptr<T>
只给出T
类型的指针。但是,这样做会假设对象已经通过std::shared_ptr<T>
进行管理,如果在堆栈上分配了对象,则会产生混乱:
struct S: std::enable_shared_from_this<S> {
std::shared_ptr<S> get_object() {
return this->shared_from_this();
};
}
int main() {
std::shared_ptr<S> ptr1 = std::make_shared<S>();
std::shared_ptr<S> ptr2 = ptr1->get_object();
// ...
}
在实际情况中,可能存在一些条件,在该条件下返回当前对象的std::shared_ptr<T>
。
答案 1 :(得分:2)
还有一些用例,您无法像不透明指针一样使用模板struct A : std::enable_shared_from_this<A> {};
extern "C" void f_c(A*);
extern "C" void f_cpp(A* a) {
std::shared_ptr<A> shared_a = a->shared_from_this();
// work with operation requires shared_ptr
}
int main()
{
std::shared_ptr<A> a = std::make_shared<A>();
f_c(a.get());
}
。
在这种情况下,有这个有用:
在some_file.cpp
中struct A;
void f_cpp(struct A* a);
void f_c(struct A* a) {
f_cpp(a);
}
在some_other.c
中Dictionary<string,object>
答案 2 :(得分:2)
假设我想代表一个计算树。我们将添加一个表示为从表达式派生的类,其中包含两个指向表达式的指针,因此可以递归地计算表达式。但是,我们需要在某个地方结束评估,所以让我们自己评估数字。
class Number;
class Expression : public std::enable_shared_from_this<Expression>
{
public:
virtual std::shared_ptr<Number> evaluate() = 0;
virtual ~Expression() {}
};
class Number : public Expression
{
int x;
public:
int value() const { return x; }
std::shared_ptr<Number> evaluate() override
{
return std::static_pointer_cast<Number>(shared_from_this());
}
Number(int x) : x(x) {}
};
class Addition : public Expression
{
std::shared_ptr<Expression> left;
std::shared_ptr<Expression> right;
public:
std::shared_ptr<Number> evaluate() override
{
int l = left->evaluate()->value();
int r = right->evaluate()->value();
return std::make_shared<Number>(l + r);
}
Addition(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right) :
left(left),
right(right)
{
}
};
请注意,使用Number::evaluate()
实施return std::shared_ptr<Number>(this);
的“明显”方式会被破坏,因为它会导致双重删除。