数组中对象的范围

Scope of object in an array

本文关键字:范围 对象 数组      更新时间:2023-10-16

假设您在c++中有一个对象数组,您从数组中删除了其中一个对象。什么时候调用对象的析构函数?由于c++没有自动垃圾收集,如果析构函数在从数组中删除后立即被调用,这似乎很奇怪。但是对象是否一直分配到数组超出作用域?这似乎会导致内存泄漏。

编辑:

将数组中的一个元素设置为另一个对象,而不是"remove"。

另外,当一个元素从std::vector中移除时,会发生什么呢?

不能"从数组中删除其中一个对象"。数组有固定的大小。所有的内容在创建数组时被构造,在数组本身被销毁时被销毁。

如果您只是给数组元素赋一个新值,那么您调用了对象的=操作符,它的行为与您有一个简单的独立变量并为其赋一个新值没有什么不同。没有对象必须被构建或破坏。如果有任何新对象,它来自编译器为赋值语句右侧生成的临时对象。语句完成后,临时对象被销毁。数组中的对象保持不变。

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

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

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

对象不能从这类数组中"移除"。当ArrayOfStrings超出作用域时,它会自动删除数组中的所有字符串。如果在此数组中编辑对象,则该对象本身将被更改。你实际上改变了字符串本身,而不是指针或引用。

如果你有一个指针数组,那么c++构造所有的指针,但是你必须自己管理它们指向什么:

std::string* ArrayOfPointersToStrings[10];

你可以手动删除数组指针指向的字符串,但你必须自己做所有的事情。当arrayofpointerstostring超出作用域时,它不会删除字符串所指向的任何内容。如果不先删除指针就编辑它,就会造成内存泄漏,这很糟糕。

如果你有一个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.

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

使用赋值操作符将RHS的内容复制到数组中的对象,通常不会对RHS上的对象产生任何影响。数组中的内存会被覆盖。没有新对象被创建或删除(除非你做了像obj1 = obj2 = obj3这样的事情,这是一个完整的"另一个蠕虫罐……")

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

对于"c风格"数组,对象本身的存在时间和它不在数组中时一样长。

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