我基本上是这样设置的:
class B { /* ... */};
class C1 : public B { /* ... */};
class C2 : public B { /* ... */};
class X
{
std::vector<shared_ptr<B>> m_vec;
void addToVector(B* b);
}
addToVector
无法知道有多少类派生自 B 并且不应该关心。它将被这样调用:
someFunction() {
C1 tmp;
/* do something with tmp */
m_myX.addToVector(&tmp);
}
所以在 someFunction
的末尾,tmp 超出范围并将被删除。 addToVector
必须将 shared_ptr push_back 到 vector 中的 tmp 拷贝,但它如何做到这一点?
void X::addToVector(B* b)
{
int i = sizeof(b); // allways sizeof(B) :(
shared_ptr<B> np(b);
m_vec.push_back(np); // garbage collected after calling fn returns :(
}
它应该做的是:
- 通过调用正确类的复制构造函数/操作符来复制b指向的对象
- 将该拷贝的 shared_ptr 推回 vector 中。
我该怎么做?
最佳答案
您正在堆栈上创建一个对象,然后将其地址提供给 shared_ptr
,它将尝试删除
堆栈上的一个对象,这是未定义的行为。
解决方案是停止这样做:
void someFunction() {
C1* c = new C1;
/* do something with *c */
m_myX.addToVector(c);
}
现在堆上有一个对象,它可以由 shared_ptr
拥有。无需复制它。
这只有在 B
有一个虚拟析构函数时才能正常工作,但是可以通过首先创建一个 shared_ptr 来避免这种情况(并且代码可以变得更安全和更清晰):
void someFunction() {
auto c = std::make_shared<C1>();
/* do something with *c */
m_myX.addToVector(c);
}
void X::addToVector(std::shared_ptr<B> b)
{
m_vec.push_back(np);
}
现在堆对象一创建就由 shared_ptr
管理,然后安全地存储在 vector 中。
关于c++ - 我如何正确地将 shared_pointers 添加到可能的派生类到 std::vector 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30478182/