我以为我知道如何在 C++ 中处理内存管理,但这让我感到困惑:
考虑以下代码:
struct A {
int i;
};
int main(int argc, char* argv[]) {
A a{ 5 }; //Constructs an A object on the stack
A* b = new A{ 7 }; //Constructs an A object on the heap and stores a pointer to it in b
A* c = new A[] { //Construct an array of A objects on the heap and stores a pointer to it in c
{ 3 },
{ 4 },
{ 5 },
{ 6 }
};
std::cout << "a: " << a.i << "\n"; //Prints 'a: 5'
std::cout << "b: " << b->i << "\n"; //Prints 'b: 7'
std::cout << "c: " << c[0].i << "; " << c[1].i << "; " << c[2].i << "; " << c[3].i << "\n";
//Prints 'c: -33686019; -1414812757; -1414812757; -1414812757'
delete b;
delete[] c;
return 0;
}
我不明白为什么 c
的最后打印输出会打印出那些奇怪的数字。如果我像这样向 A 添加构造函数:
struct A {
A(int i) : i{i} {}
int i;
};
那么最后打印出来的输出就变成了:
'c: 3; 4; 5; 6'
本应如此。但是现在 delete[] c;
会给我一个运行时错误(看起来不是异常),说 MyGame.exe 触发了一个断点。
(我正在工作VS2013)。
此外,如果我将行 A* c = new A[] {
更改为 A* c = new A[4] {
错误消失,一切正常正如预期的那样。
所以我的问题是: 为什么会有奇怪的数字?如果我不定义构造函数,数组中的 A 对象是否会以某种方式正确构造? 为什么我需要显式指定数组大小,即使没有它也可以编译和链接?以这种方式在堆栈上初始化数组不会给我运行时错误(我测试过它以确保)。
最佳答案
这是一个错误:
A* c = new A[] { {3}, {4}, {5}, {6} };
您必须将维度放在 []
中。使用 new
时,无法从初始化列表中推导出数组维数。
将 4
放在这里使您的代码对我来说可以正常工作。
您的编译器显然具有将 new A[]
视为 new A[1]
的“扩展”。
如果你在标准模式下编译(使用 gcc 或 clang,-std=c++14 -pedantic
),这总是一个好主意,编译器会告诉你这样的事情。将警告视为错误,除非您真的确定它们不是错误:)
关于c++ - 堆上的结构数组未正确初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33225139/