【发布时间】:2016-01-18 10:23:37
【问题描述】:
我以为我知道如何在 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 has triggered a breakpoint.(我在VS2013 中工作)。
此外,如果我将行 A* c = new A[] { 更改为 A* c = new A[4] {,错误就会消失,一切都按预期工作。
所以我的问题是: 为什么会有奇怪的数字?如果我不定义构造函数,数组中的 A 对象不会以某种方式正确构造吗? 为什么我需要明确指定数组大小,即使没有它也可以编译和链接?以这种方式在堆栈上初始化数组不会给我一个运行时错误(我测试过它是肯定的)。
【问题讨论】:
-
如果要在堆上分配数组,则需要指定数组的大小。您分配的是指针(例如
A*)而不是数组。从中读取会调用未定义的行为。 -
here 编译失败!
-
奇怪的数字是因为你的编译器有点坏。 g++ 5.1 说“错误:']' 标记之前的预期主表达式”和“错误:'A [1]' 的初始化程序太多”。 VS 2015 说“错误 C3078:必须在新表达式中指定数组大小”。 VS2013 对该代码的影响尚不清楚。
标签: c++ arrays structure heap-memory