我正在学习c ++ 11的功能,特别是shared_ptr
,我在引用this
并将其作为其他类的参考时遇到了问题。
这样做的原因是我有一个Simulation
实例传递给模拟中的其他实例(例如Apple
),因此他们可以自己修改模拟,甚至将自己从模拟中移除模拟。
在我更复杂的代码中,我得到double free
错误(当程序存在时),据我所知from here我不应该在同一个原始对象上创建shared_ptr
两次。当Simulation类不知道this
已经是Apple
时,如何将shared_ptr
作为this
对象传递给shared_ptr
?
我的想法是在初始化参数中传递shared_ptr
,但这似乎是多余的,例如:
// The argument is a std::shared_ptr<Simulation>
simulation->initSomethingElse(simulation);
也许我试图以一种不寻常的模式实现这一点,或者我的理解可能不太正确?也许有一种更好的方法可以做到这一点?
我在下面有一个简化的例子:
#include <memory>
class Simulation;
class Apple {
public:
void init(std::shared_ptr<Simulation> simulation) {
this->simulation = simulation;
};
private:
std::shared_ptr<Simulation> simulation;
};
class Simulation {
public:
void initSomethingElse() {
auto apple = std::shared_ptr<Apple>(new Apple());
// incorrect second reference to the raw pointer
apple->init(std::shared_ptr<Simulation>(this));
};
};
int main() {
auto simulation = std::shared_ptr<Simulation>(new Simulation());
simulation->initSomethingElse();
return 0;
}
答案 0 :(得分:8)
首先想到的是使用enable_shared_from_this
:http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
但是我想到的第二件事是Simulation应该管理Apple的生命周期,因此Apple无需管理Simulation的生命周期。因此,最好不让Apple持有shared_ptr<Simulation>
- 只有main()
或某些高级功能才能管理模拟的生命周期。
如果您不小心,最终会得到循环引用。不要假设C ++ 11中的每个指针都应该是shared_ptr。
答案 1 :(得分:1)
使用enable_shared_from_this
,这样对象上的函数就可以为自己创建一个新的shared_ptr
。您将要执行此操作,而不是apple->init(std::shared_ptr<Simulation>(this));
行,以便为shared_ptr
创建第二个Simulation
。您还希望在某处调整或保存apple
shared_ptr
,因为Apple
仅在initSomethingElse()
正在运行时存在,而不是{{1}}看起来很有用......?