代码如下:
class A {
private:
int *anArr;
int id;
public:
A() {
id = 0;
anArr = new int[10];
}
A(int i) {
id = i;
anArr = new int[10];
}
~A() {
delete[] anArr;
std::cout << "Class A id : " << id << " destructor" << std::endl;
}
};
class B {
private:
A *anArr;
public:
B() {
anArr = new A[10];
}
~B() {
std::cout << "Class B destructor" << std::endl;
delete[] anArr;
}
void changeAnElement() {
anArr[2] = A(1);
anArr[2] = A(2);
}
};
int main()
{
B b;
b.changeAnElement();
return 0;
}
输出:
Class A id : 1 destructor
Class A id : 2 destructor
Class B destructor
Class A id : 0 destructor
Class A id : 0 destructor
Class A id : 0 destructor
Class A id : 0 destructor
Class A id : 0 destructor
Class A id : 0 destructor
Class A id : 0 destructor
// Gives heap error here
因此,如果我没记错的话,当我更改对象数组的元素时,它不会调用析构函数。
我的第一个问题是更改索引处的旧对象会发生什么?里面的数组会不会泄露?我以为我需要自己调用析构函数来防止内存泄漏,但它会给出堆错误。
第二个问题是当调用已更改对象的析构函数时出现堆错误 (Expression: _CrtlsValidHeapPointer(block)
)。我不知道为什么,它适用于在构造函数中创建的那些。
谢谢!
最佳答案
My first question is what happens to old object at the changed index?
数组中的对象永远不会去任何地方。 “旧”对象保留在该索引中。您对该对象调用赋值运算符。赋值运算符修改对象。
Does the array in it leak?
对象在赋值之前指向的数组确实泄漏了,是的。
I thought that I need to call destructor myself to prevent memory leak
您使用 new[]
创建了对象,因此您确实需要调用 delete[]
,这确实会调用析构函数。
but it gives heap error
那是因为你忘了关注rule of 3 (or of 5) .
anArr[2]
包含与临时 A(2)
包含的指针相同的指针,但是由于临时的析构函数已经运行,它已经删除了数组和 anArr[2]
的析构函数然后尝试再次删除它。这是不能做的事情之一。
结论:
- 当您进行手动内存管理时,请遵循规则 3
- 不要进行手动内存管理。在此处改用
std::vector
或std::array
。
关于c++ - 删除对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40871279/