用std :: shared_ptr替换向量中的原始指针

时间:2013-08-13 06:40:37

标签: c++ pointers std shared-ptr stdvector

我有以下结构:

typedef Memory_managed_data_structure T_MYDATA;
std::vector<T_MYDATA *> object_container;
std::vector<T_MYDATA *> multiple_selection;
T_MYDATA * simple_selection;

编辑:这可能非常重要:Memory_managed_data_structure包含一些指向其他数据的苦涩原始指针。

它旨在成为内存管理对象(object_container)的原始容器的非常简单的表示,然后是“multiple_selection”数组(用于选择范围内的许多对象并使用它们执行各种操作)和“simple_selection”指针(用于对单个对象执行这些操作)。

所有对象的生命周期由object_container管理,而multiple_selection和simple_selection只指向其中一些对象。 multiple_selection和simple_selection可以根据需要无效,只能删除object_container对象。

系统运行正常,但我现在正试图进入shared_ptrs并希望将结构更改为:

typedef Memory_managed_data_structure T_MYDATA;
std::vector<std::shared_ptr<T_MYDATA> > object_container;
std::vector<std::shared_ptr<T_MYDATA> > multiple_selection;
std::shared_ptr<T_MYDATA> simple_selection;

同样,对象容器将是“所有者”,其余的只是指向它们。我的问题是,这个计划会在应用程序中肆虐吗?在滚雪球进入这些变化之前,我应该知道些什么吗?这里不是shared_ptr适当的指针吗?。

我可以在某种程度上保证在multiple_selection或simple_selection中不存在任何对象,如果它首先不在object_container中。当然,在multiple_selection或simple_selection中都没有调用删除。

感谢您的时间。

编辑:忘记提及,之前从未使用过任何这些自动指针,所以我可能会对它们的用途感到非常困惑。任何提示和经验法则将不胜感激。

2 个答案:

答案 0 :(得分:1)

  

我可以保证不存在任何对象   multiple_selection或simple_selection如果不在   object_container首先。

如果您确定150%,那么就不需要智能ptr。

我认为在这种情况下您可能需要它的原因是调试。 如果你描述 - multiple_selection和simple_selection不是 shared_ptr ,而是 weak_ptr

代码错误

  std::vector<int*> owner_vector;
  std::vector<int*> weak_vector;

  int* a = new int(3);

  owner_vector.push_back(a);
  weak_vector.push_back(a);

  std::for_each(
      owner_vector.begin(),
      owner_vector.end(),
      [](int* ptr) {
        delete ptr;
      }
  );

  std::for_each(
      weak_vector.begin(),
      weak_vector.end(),
      [](int* ptr) {
        *ptr = 3; // oops... usage of deleted pointer
      }
  );

你可以通过智能指针捕获它:

  std::vector<std::shared_ptr<int>> owner_vector;
  std::vector<std::weak_ptr<int>> weak_vector;

  {
    auto a = std::make_shared<int>();

    owner_vector.push_back(a);
    weak_vector.push_back(a);
  }

  std::for_each(
      owner_vector.begin(),
      owner_vector.end(),
      [](std::shared_ptr<int>& ptr) {
        ptr.reset(); // memory delete
      }
  );

  std::for_each(
      weak_vector.begin(),
      weak_vector.end(),
      [](std::weak_ptr<int>& ptr) {
        assert(!ptr.expired()); // guarantee to be alive
        auto shared_ptr = ptr.lock();
        *shared_ptr = 3;
      }
  );

在上一个示例中,您将断言失败,但未定义/分段错误。在非调试的情况下,您可以禁用shared_ptr 开销

答案 1 :(得分:1)

你说,对象容器将是所讨论对象的“所有者”。在这种情况下,你有一个明确的拥有关系,使用std :: shared_ptr并不理想。相反,坚持你所拥有的。

但是,如果你不能保证,在删除之前已经从multiple_selection和/或simple_selection中删除了一个指针,你必须采取行动。一个可能的操作可能是,您使用shared_ptr。在这种情况下,一个对象仍然可以继续存在于其中一个选择中,如果它被从object_container中删除(通过shared_ptr :: reset或只是赋值空值)。

另一种方法是确保彻底删除对象:如果要删除某些内容,请从选择和object_container中删除对它的所有引用,然后删除它。如果严格遵循此方案,则不需要shared_ptr的开销。