我经常发现自己 漫不经心地写了一些类,这些类添加了指向对象的指针,这些对象后来被销毁到列表中,这导致了很多段错误,但是问题是有时我只是可以'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
实例(如果{{1 }}例如,复制构造函数是私有的。
当然,一旦您尝试在代码中的其他地方使用OtherObject
,每个指针指向的内存将被销毁。
我编写了很多Python代码,并且经常使用这种结构非常,其中一种方法使用仅存在于该方法范围内的对象填充可迭代对象。有没有办法在C ++中有效地做到这一点?我可以做自己的内存管理来使方法中的临时对象保持活动状态,超出方法范围吗?
答案 0 :(得分:6)
在C ++中创建指针列表的正确范例是什么?
结合std::list
或container之类的smart pointer类(请参见here)std::shared_ptr
(或其他std::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 ++实现中,您可以找到工具,例如valgrind或address sanitizer的Clang或GCC调试,然后避免使用memory leaks(详细信息取决于编译器和/或OS)。在少数情况下(可能是少数),您可以考虑使用垃圾收集器库(例如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 ++编程,正是因为它具有许多有用的工具。
答案 1 :(得分:5)
不,您没有理由这样做:
OtherObject other_object = create_other_object();
other_objects.push_back(&other_object);
这将创建一个临时对象,然后将指针存储在列表中,然后销毁该对象。
这是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());
}