创建指针列表的正确范例是什么?

use*_*473 0 c++ memory-management

我发现自己经常不假思索地编写类,这些类添加指向对象的指针,这些对象后来被销毁到列表中,这导致了很多段错误,但问题是有时我根本无法提出比存储列表更好的解决方案指针.我认为,在C++中似乎没有一种简单的方法可以"存储你无法复制的临时对象".有没有关于如何有效地做到这一点的范例?

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

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

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

当然,一旦你尝试other_objects在代码中的其他地方使用,每个指针指向的内存将被破坏.

我写了很多的Python代码,我用这种结构非常频繁,其中一个方法填充的迭代与该方法的范围内单独存在的对象.有没有办法在C++中有效地做到这一点?我可以自己进行内存管理,以使方法中的临时对象保持活动超出方法范围吗?

Bas*_*tch 6

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

std::list(或者某些其他容器)与一些智能指针类(参见此处)(例如std::shared_ptr或)组合在一起std::unique_ptr.

根据经验(有时是错误的)避免使用原始指针并且更喜欢智能指针.内存管理是一个棘手的话题.如果您阅读了一些关于垃圾收集的书(例如GC手册),您将学习相关的概念,术语和技术(这些甚至适用于手动内存管理,例如引用计数 - 有些人认为这是GC的原始形式) .循环引用很难处理(请注意弱引用,例如std::weak_ptr).

这里需要花费大量的时间和空间来详细解释所有这些(而且我没有时间或动力,甚至没有所有技能).阅读一本好的C++编程书并参考一些C++参考(后来可能是C++ 11标准n3337或更新版本).请注意,C++ 的内存模型很难理解(对任何人而言).

要注意五个规则.

在某些操作系统和/或C++实现,你可以找到的工具,比如Valgrind的地址消毒剂GCC,这将有助于您调试,然后避免内存泄漏(细节编译器和/或OS特定).在少数 情况下(可能是其中的一小部分),您可以考虑使用垃圾收集器库(例如Boehm的GC,请参阅此内容MPS).

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

我不知道有任何有效,通用和简单的方法(赖斯的定理让我相信没有一个)来管理记忆.你的里程会有所不同.您需要准确理解您的内存管理和其他编程约束和目标,并进行自己的权衡.见Norvig的观点.有没有银弹.


PS.C++是一种非常困难的编程语言.准备好自己花费大量时间(几年,而不是几个月;也许几十年)并努力学习它.另外,从灵感来看,也可以看一些用C++ 编写的编写良好的免费软件的源代码.我并不认为自己是C++大师(即使我的日常工作是为它设计和实现一些静态源代码分析器).我相信这个星球上可能只有几十个(或者几百个)C++大师,我不在其中.

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


Mat*_*her 5

不,你没有理由这样做:

  OtherObject other_object = create_other_object();
  other_objects.push_back(&other_object);
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 它创建一个对象并按值返回它.在这种情况下,请将其包装make_unique以获得副本.这种模式通常不是很有用而且不实用.
  • 它在堆上创建一个新对象,并期望调用代码处理内存管理.因此原型是:std::unique_ptr<OtherClass> create_other_object();
  • 它创建一个新对象,但不希望调用代码处理内存管理,在这种情况下原型应该是 OtherClass* create_other_object();

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

std::vector<std::unique_ptr<OtherClass>> other_objects;
void method() {
    other_objects.push_back(create_other_object());
}
Run Code Online (Sandbox Code Playgroud)