【问题标题】:What is the proper paradigm of creating a list of pointers?创建指针列表的正确范例是什么?
【发布时间】:2019-06-10 20:14:54
【问题描述】:

我发现自己如此频繁地不假思索地编写了添加指向对象的指针的类,这些对象后来被销毁到列表中,这导致了很多段错误,但问题是有时我只是可以't 想出比存储指针列表更好的解决方案。我的想法是,似乎没有一种简单的方法可以在 C++ 中“存储无法复制的临时对象”。关于如何有效地做到这一点,我是否缺少一个范例?

例如,我将有一个看起来像这样的类:

class MyClass
public:
   std::vector<OtherClass *> other_objects;
   void method() {
      OtherObject other_object = create_other_object();
      other_objects.push_back(&other_object);
   }

您可能想要这样做的一个原因是因为您在其他地方使用了 other_objects(作为其他函数的参数)并且您无法复制 OtherObject 实例(如果 OtherObject 复制构造函数是私有的,则可能发生这种情况例如)。

当然,一旦你尝试在代码的其他地方使用other_objects,每个指针指向的内存都将被销毁。

我编写了很多 Python 代码,并且我经常非常使用这种结构,其中方法使用仅存在于方法范围内的对象填充可迭代对象。有没有办法在 C++ 中有效地做到这一点?我可以自己进行内存管理以使方法中的临时对象在方法范围之外保持活动状态吗?

【问题讨论】:

  • 最好不要使用原始指针,而是使用smart pointers
  • 我不熟悉这个概念,我只是C++的初学者。您能否分享一些参考资料或详细说明它如何解决我的问题?
  • 正如我所写,学习这些高级主题至少需要一年时间。看你的 C++ 书,一年的学习不能真正简化为对 stackoverflow 的简短回答。 C++ 很难。
  • @texasbruce:我认为掌握 C++ 需要十年时间。一年肯定不够。并且很少有人掌握 C++(我不声称,即使我知道其中一些)。

标签: c++ memory-management


【解决方案1】:

在 C++ 中创建指针列表的正确范例是什么?

std::list(或其他container)与smart pointer 类(参见here)结合起来,例如std::shared_ptrstd::unique_ptr

根据经验(有时是错误的)避免使用raw pointers 并更喜欢智能指针。 Memory management 是一个棘手的话题。如果您阅读有关garbage collection 的书籍(例如GC handbook),您将学习相关的概念、术语和技术(这些甚至适用于manual memory management,例如reference counting - 有些人将其视为原始形式GC)。 Circular references 处理起来很痛苦(注意weak references,例如std::weak_ptr)。

在这里详细解释所有这些需要很多的空间和时间(我没有时间或动力,甚至没有所有的技能)。阅读一本好的C++ programming 书籍并参考一些C++ reference(稍后可能参考C++11 标准n3337 或更新的东西)。请注意,C++ 的 memory model 很难理解(对任何人来说)。

注意rule of five

在某些操作系统和/或 C++ 实现中,您可以找到工具,例如 valgrindClangGCCaddress sanitizer,它们应该可以帮助您调试然后避免使用 memory leaks(详情是编译器和/或操作系统特定的)。在少数情况下(可能是少数),您可以考虑使用垃圾收集器库(例如Boehm's GC,参见this,或MPS)。

有没有办法在 C++ 中有效地做到这一点?

我不知道任何有效、通用和简单的方法(Rice's theorem 让我相信不可能有一种方法)来管理内存。您的里程会有所不同。您需要准确了解您的内存管理和其他编程约束和目标,并做出自己的权衡。请参阅 Norvig 的 opinion。有No Silver Bullet


PS。 C++ 是一种极其困难的编程语言。准备好花费大量时间(数年,而不是数月;也许是数十年)并努力学习它。为了获得灵感,还请查看一些用 C++ 编写的写得很好的free software 的源代码。我并不声称自己是 C++ 大师(即使我的日常工作是为它设计和实现一些静态源代码 analyzers)。我相信这个星球上可能只有几十个(或者几百个)C++ 高手,而我不在其中。

PPS。我有偏见,但我推荐在你的开发机器上使用using Linux 来学习 C++ 编程,正是因为它有很多有用的工具。

【讨论】:

    【解决方案2】:

    不,你没有理由这样做:

      OtherObject other_object = create_other_object();
      other_objects.push_back(&other_object);
    

    这会创建一个临时对象,并将指针存储在一个列表中,然后该对象被销毁。

    这是与 Python 的主要区别。在 Python 中,每个对象都是对 Python 对象的引用,甚至是整数。在 C++ 中,您在堆栈(如您的)或堆(通过 newmake_unique... 创建)上有对象。如果你想模仿 Python 的行为,你需要堆上的对象。

    只有三种有效模式,具体取决于 create_object() 的作用:

    • 它创建一个对象并按值返回它。在这种情况下,用make_unique 包装它以获取副本。这种模式通常不是很有用,也不实用。
    • 它在堆上创建一个新对象并期望调用代码来处理内存管理。因此原型是:std::unique_ptr&lt;OtherClass&gt; create_other_object();
    • 它创建了一个新对象但不期望调用代码处理内存管理,在这种情况下原型应该是OtherClass* create_other_object();

    在你的情况下,可能是第二种情况:

    std::vector<std::unique_ptr<OtherClass>> other_objects;
    void method() {
        other_objects.push_back(create_other_object());
    }
    

    【讨论】:

      猜你喜欢
      • 2011-06-14
      • 1970-01-01
      • 2016-09-25
      • 1970-01-01
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 1970-01-01
      相关资源
      最近更新 更多