c++ - 我如何正确地将 shared_pointers 添加到可能的派生类到 std::vector 中?

标签 c++ vector polymorphism shared-ptr object-slicing

我基本上是这样设置的:

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/

相关文章:

c++ - 如何将c#中的单例转换为c++中的单例?

c++ - 解析如何工作或者什么使类型完整或不完整?

Java继承问题

c# - 多态和虚方法

C++:如何解决具有多个多态输入的方法调用?

c++ - 有没有办法以编程方式在 osx 上隐藏碳应用程序?

c++ - 未正确映射 OpenGL 纹理立方体

c++ - asio::buffer 类型用于发送 std::vector 和 std::string

c++ - 为什么 C++ 中的 vector 不会自动调整大小

c++ - vector 下标超出范围