数组中对象的范围

时间:2011-08-24 18:59:14

标签: c++ memory-leaks destructor

假设您在C ++中有一个对象数组,并从数组中删除其中一个对象。该对象的析构函数何时被调用?由于C ++没有自动垃圾收集,如果析构函数在从数组中删除后立即被调用,这似乎很奇怪。但是,在阵列超出范围之前,对象是否保持分配状态?这似乎会导致内存泄漏。

编辑:

而不是“删除”如何将数组的一个元素设置为不同的对象。

此外,从std::vector删除元素后会发生 的行为吗?

4 个答案:

答案 0 :(得分:2)

您不能“从阵列中删除其中一个对象。”数组具有固定的大小。所有内容都是在创建数组时构造的,并在数组本身被销毁时被销毁。

如果您只是为数组元素分配一个新值,那么您正在调用该对象的=运算符,它的行为与您拥有一个简单的独立变量并为其分配新值的行为没有区别。不必构造或销毁任何对象。如果有任何新对象,则它来自编译器为赋值语句的右侧生成的临时对象。语句完成后,临时对象将被销毁。数组中的对象保持不变。

当您从vector中删除某个项目时,会调用其析构函数,正如您所期望的那样,后面的元素会向下移动以填补空白。

答案 1 :(得分:1)

当你声明一个C ++数组时,它会构造堆栈中的所有对象,并且它们会一直存在,直到数组本身被删除:

std::string ArrayOfStrings[10]; //There are now ten strings here

不能从这种数组中“移除”对象。当ArrayOfStrings超出范围时,它会自动删除数组中的所有字符串。如果编辑此数组中的对象,则该对象本身会发生更改。你实际上改变了字符串本身,而不是一些指针或引用。

如果你有一个指针数组,那么C ++构造所有的指针,但你必须管理他们自己指出的内容:

std::string* ArrayOfPointersToStrings[10];

您可以手动删除数组中指针指向的字符串,但您必须自己完成所有这些操作。当ArrayOfPointersToStrings超出范围时,它不会删除字符串所指向的任何内容。如果您编辑指针而不先删除它,那就是内存泄漏,这很糟糕。

如果你有一个std :: vector,C ++只根据你构造它的方式构造一些对象:

std::vector<std::string> VectorOfStrings(10);

这会创建一个动态字符串数组。可以从矢量中移除对象,在这种情况下,矢量会立即删除它并为您重新排列其余部分。如果编辑此数组中的对象,则该对象本身会发生更改。你实际上改变了字符串本身,而不是一些指针或引用。

澄清评论:

char *myLiteral = "APPLE";
//"APPLE" is an immutable string, myLiteral points at it.
std::string s= myLiteral; 
std::string t = myLiteral;
//s and t each makes a _seperate_ _mutable_ copy of "APPLE"
s[3] = '?'; 
//s is now "APP?E", because we just changed the L.  NO COPY WAS DONE. 
std::cout << t[3];
//displays "L", because t's copy was never changed.

答案 2 :(得分:0)

对于像std::vector这样的标准容器,当remove方法完成时,对象已被破坏。

对于“c-style”数组,对象本身将持续与它不在数组中时一样长。

对象的生命周期取决于对象的分配位置。如果它在堆栈上,当当前作用域结束时它被释放,如果它在堆上,那么在它被调用delete之前它不会被释放。如果永远不释放对象,则最后一种情况会导致内存泄漏。

答案 3 :(得分:0)

您无法从vanilla C ++数组中删除对象。当您声明一个特定大小的数组时,无论是在堆栈还是堆上,假设分配成功,都会分配足够的内存来创建该类型的N个对象,并使用适当的任何构造函数创建它们。

使用赋值运算符将RHS的内容复制到数组中的对象通常不会对RHS上的对象执行任何操作。数组中的内存被覆盖。没有创建或删除新对象(除非您执行obj1 = obj2 = obj3之类的事情,这是一整套'其他蠕虫......)