【问题标题】:Correct life-cycle management of objects in C++C++ 中对象的正确生命周期管理
【发布时间】:2012-12-28 06:46:21
【问题描述】:

我有几个简单的 C++ 类来保存数据。它们是分层的,每个都包含一个指向孩子的指针列表(因为我在内存中有很多,我不想复制它们)。

我只在最高级别工作(将其传递给函数),并且希望每个级别的析构函数都销毁其子级,所以我要做的就是释放所有子级,只需在最顶层的父级上调用 delete .当在堆栈上创建某些类时,这会导致问题,但这实际上只是问题的症状。

正如我所见,我需要在同一级别上创建和销毁对象,从而知道是否应该调用 delete。但是,这将迫使我在代码中每次使用后都持有指向所有子级的指针并销毁它们,这是一个比在最顶层的父级上调用 delete 更脏的解决方案。

所以,我的选择是:

  1. 永远不要在堆栈上定义它们 (BAD)
  2. 在构造函数中传递一个布尔值,指示是否应删除此对象 (BAD)
  3. 在每次使用后手动删除对象,具体取决于我创建它们的方式 (BAD)
  4. “本地”复制项目(因为可能有数千个,所以不好)
  5. 智能指针?一些框架? (我能用的东西比较有限)

我错过了什么吗?还有其他想法吗?

谢谢, 瓦迪姆。

【问题讨论】:

  • 你能升级(如果有必要的话)并使用 C++11 吗?这是std::move 的典型代表。
  • 我认为我不能升级到 C++11,我们使用的是 gcc 3.2,而且这个项目(或问题)对于升级编译器来说不够重要。
  • 另一件事 - 这不仅仅是一个 C++ 问题,我所做的某处存在 OOP 设计缺陷,我找不到好的解决方案。
  • 你对问题的描述太抽象了。我不明白为什么会出现你不知道某个对象是堆栈分配还是堆分配的情况。
  • 我只定义类,我无法控制它们在使用时的实例化方式。我会纠正自己 - 我不想控制它们的实例化方式,否则我会使用工厂来解决我的问题。对于非常简单的 POCO,我似乎太过分了。

标签: c++ memory-management


【解决方案1】:

在 C++11 中,您将定义一个移动构造函数并在对象超出范围之前调用 std::move,以便它可以传递资源的所有权,否则将获得 deleted。

在 C++03 中,可以在没有语言形式的情况下定义相同的功能,但您必须在对象为空的地方添加一个状态。这通常通过引入默认构造函数并实现swap 来完成。

被删除的指针应该默认构造为null,并且在交换(或复制构造函数或任何函数)将指针传递到将超出范围的新容器对象之后,它们被设置为@ 987654324@ 所以delete 没有任何效果(并且使对象无法使用,这很“脏”,但还不错,因为您可以轻松确保对象在移出后不用于任何事情)。

【讨论】:

  • 这与简单地复制是否不同(性能虎钳)?
  • @Vadim 没有进行“深度”复制。总之,您只需复制指针,然后将旧指针设置为 NULL 以避免重复删除。从那里开始,一切正常。
  • 我可能遗漏了一些东西。如果我将其中一个字符串定义为局部变量,则数据(类的成员)将保留在堆栈中,而不管我将如何处理指针。如何避免将其从堆栈中复制出来?
  • @Vadim 你没有说堆栈上的字符串或原始数据;你说你有一个对象层次结构,堆栈中的顶部对象。
  • 对不起,这是一个愚蠢的错误。意思是说我是否将其中一个类定义为局部变量。不知道我为什么写“字符串”。
【解决方案2】:

考虑将子对象保存在std::list 中。不使用new,而是编写一个函数,使用push_back() 创建一个新的孩子并返回一个指向它的指针。您不需要直接销毁孩子,并且可以防止泄漏。

【讨论】:

    猜你喜欢
    • 2012-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 2013-08-08
    • 2011-05-09
    相关资源
    最近更新 更多