我有一些像这样构造的代码:
#include <memory>
#include <vector>
using namespace std;
struct demo {
vector<shared_ptr<demo>> foo{shared_ptr<demo>(this)};
void append(){
foo.push_back(make_shared<demo>());
}
};
demo dummy(/* accept some arguments */){
demo a{};
a.append();
return a;
}
int main()
{
demo bar=dummy();
return 0;
}
虚函数只是根据新构建的演示实例上的参数进行一些处理并返回它。 (我很确定以上内容足以揭露问题)
它编译良好,没有错误,但它不会自动终止。 (我在Win7上使用G ++的MinGW)。
然后我尝试解决。我添加了一个复制构造函数(以及一个显式的默认构造函数),然后使用new
仅在main函数中保留一个指向demo的指针。因此代码将类似于:
...
struct demo {
vector<shared_ptr<demo>> foo {shared_ptr<demo>(this)};
void append() {
foo.push_back(make_shared<demo>());
}
demo(){
};
demo(const demo& instance): foo(instance.foo) {
}
};
...
int main()
{
// demo bar=dummy();
demo* bar=new demo(dummy());
delete bar;
return 0;
}
然后就行了。但我仍然怀疑这些线背后的机制。您能解释一下new
构造变量和通常声明变量之间的区别吗?
编辑:所以最终还是将push_back
this
作为构造函数中的struct成员导入到向量中? (由于这个原因,这是因为我的矢量的其余部分存储了除第一个之外的所有shared_ptr
,换句话说,即使向量pop_back
为空,它仍然可以返回{{1 }})
答案 0 :(得分:3)
这是一个更简单的示例,可以重现您的问题:
struct demo {
shared_ptr<demo> foo{this};
};
int main()
{
demo bar;
}
问题是您在成员中存储了this
的共享指针。因此,当一个demo
实例被销毁时,共享指针会递减,当共享指针递减到零时,它将再次删除该对象,从而导致未定义的行为。
即使问题不存在,仍然存在bar
是自动对象的问题。并且您可能没有共享指向自动对象的指针。但bar
确实创建了一个指向自身的共享指针。
demo* bar=new demo(dummy());
delete bar;
这样更好,因为现在对象(由bar
指向)具有动态存储,因此您可能有一个共享指针。您当然必须修复dummy
以不创建自动demo
实例。
此外,您可能没有明确delete
demo
的实例,因为内部有一个共享指向它自己。 &#34;正确&#34;处理demo
实例的方法是删除共享指针,然后处理删除:
demo* bar=new demo(dummy());
bar->foo.clear(); // this is for your vector version
//bar->foo = nullptr; // this is for my minimized example above
// object pointed by bar no longer exists
// (unless the shared pointer was copied and exists elsewhere)
但是,我觉得这个设计很混乱,不推荐它。您应该重新考虑为什么存储共享指针this
。
答案 1 :(得分:0)
在堆栈上创建a
或让shared_ptr
管理其生命周期,但不能同时执行这两项操作。当堆栈消失时,堆栈上的对象消失。