2

我有以下结构:

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 不是这里合适的指针吗?

如果它不在 object_container 中,我可以在一定程度上保证在 multiple_selection 或 simple_selection 中不存在任何对象。当然,在multiple_selection 或simple_selection 中不会调用delete。

谢谢你的时间。

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

4

2 回答 2

1

如果它不在 object_container 中,我可以在一定程度上保证在 multiple_selection 或 simple_selection 中不存在任何对象。

如果你有 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开销

于 2013-08-13T07:50:53.593 回答
1

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

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

另一种选择是确保彻底删除对象:如果要删除某些内容,请从选择和 object_container 中删除对其的所有引用,然后将其删除。如果严格按照这个方案,就不需要shared_ptr的开销。

于 2013-08-13T07:51:51.287 回答