在类构造函数中,我需要动态创建一些对象并将它们添加到向量中。这是我的代码:
ContainerClass::ContainerClass() {
for (int i = 0; i < limit; i++)
elements.push_back(SubElement());
}
这与新的SubElement()是一回事吗?我是否仍需要将这些SubElement()对象释放到ContainerClass析构函数中?
答案 0 :(得分:6)
方法1:
如果您有std::vector<SubElement> elements;
然后你会使用elements.push_back(SubElement())
。
SubElement()
在堆栈上创建SubElement
,然后将副本添加到vector
。
您不应在delete
的各个元素上调用vector
。当vector
超出范围时,它们将被破坏并解除分配。
方法2:
如果您有std::vector<SubElement*> elements;
然后你会使用elements.push_back(new SubElement())
。
new SubElement()
在堆上创建SubElement
,然后该元素的地址存储在vector
中。
在delete
超出范围之前,您需要在各个元素上调用vector
,否则您将创建内存泄漏。只有在每个元素上调用delete
时,它们才会被破坏和解除分配。
答案 1 :(得分:1)
SubElement():自动分配,新的SubElement():动态分配。
经验法则:您不需要删除未使用new创建的对象。
答案 2 :(得分:1)
不 - 他们是不同的。
只需SubElement()
创建一个自动(堆栈)对象,应该将其复制以便保存。
new SubElement()
在堆上创建一个动态分配的对象,并应分配给指向此类对象的指针。它必须最终释放,以防止内存泄漏。
答案 3 :(得分:1)
这不是一回事。在大多数面向对象的语言中,特别是具有任何类型的内置垃圾收集的语言,所有对象都在堆上分配,变量总是包含指向对象的指针,而不是对象本身。
C ++是少数面向对象语言之一,您可以通过值引用对象。
在new
的情况下,您正在创建一个对象并被赋予指向它的指针。然后,您将通过指针而不是直接引用对象。在另一种情况下,您正在堆栈上创建对象,容器将存储自己的副本。
通常,基于堆栈的副本将通过引用引用(&
背后的整个概念作为类型限定符),但这些引用通常被理解为短暂的并且通常由该事物组成。如果该东西需要存储一段时间,则被引用。
特别是在这种情况下,如果你有一个指针容器(即::std::vector<SubElement *> c
),它会存储指向对象的指针,你通常会用new
分配它们。但是标准库容器类(以及大多数其他容器类)不会为您删除指针。他们不接受指针的'所有权'。因此,您将自行负责删除它们。
如果您有一个对象容器(即::std::vector<SubElement> c
),那么您将使用c.push_back(SubElement())
表单,容器将存储您正在创建的临时对象的副本。容器确实拥有这些副本的所有权,并且还经常在内部复制它们。这就是为什么按值存储在容器中的对象需要实现复制构造函数。
有一种方法可以让容器获取指针的所有权,但只是间接地。您可以让容器存储自己拥有所有权的对象的副本。人们使用的标准类是::std::tr1::shared_ptr<T>
。您的容器声明如下:::std::vector< ::std::tr1::shared_ptr<SubElement> > c
。然后,您可以执行:c.push_back(new SubElement());
,容器将在完成后删除SubElement对象。
您应该阅读shared_ptr
,并在使用之前了解它的作用。