如何正确地将可能派生类shared_pointers添加到 std::vector 中
How do i correctly add shared_pointers to probably derived classes into a std::vector?
>我基本上有这个设置:
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
必须将 tmp 副本的shared_ptr push_back到向量中,但它怎么能做到这一点呢?
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 指向的对象的副本
- push_back该副本的shared_ptr到矢量中。
我该怎么做?
您正在堆栈上创建一个对象,然后将其地址提供给一个shared_ptr
,该将尝试在堆栈上delete
对象,这是未定义的行为。
解决方案是停止这样做:
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
管理,然后安全地存储在向量中。
你的"someFunction"看起来很奇怪...(为什么不首先创建tmp
作为shared_ptr
?
要使其工作,您必须创建"虚拟构造函数" - 在 B 中添加虚拟方法B* deepCopy() const
,并在所有子类中实现它,它的主体应该基于模式:{ return new DerivedType(*this); }
如果你想干净 - deepCopy
返回shared_ptr
并使用make_shared
。
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 如何在C++中从两个单独的for循环中添加两个数组
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 如何仅为一个函数添加延迟
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 使用std::transform将一个范围的元素添加到另一个范围中
- 如何将更多文件夹添加到c++include路径
- 如何将元素添加到数组的线程安全函数?
- QT通过C++添加映射QML项目
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 只能向C++添加一定数量的字符
- Qt和C++:将QLineEdit添加到QTabWidget中
- 将QIcon添加到QTableView单元格
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- 为什么除非添加括号,否则构造函数上的模板替换会失败?
- 'Cannot add two pointers'添加带有 WCHAR 的 LPCWSTR
- C++ "cannot add two pointers" ,将硬编码字符串添加到 CString