Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
堆上的结构数组未正确初始化 我想我知道如何处理C++中的内存管理,但这使我困惑:_C++_Arrays_Structure_Heap - Fatal编程技术网

堆上的结构数组未正确初始化 我想我知道如何处理C++中的内存管理,但这使我困惑:

堆上的结构数组未正确初始化 我想我知道如何处理C++中的内存管理,但这使我困惑:,c++,arrays,structure,heap,C++,Arrays,Structure,Heap,考虑以下代码: 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 a

考虑以下代码:

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: 3; 4; 5; 6'
应该如此。但是现在
delete[]c
将给我一个运行时错误(似乎不是例外),表明MyGame.exe触发了断点。(我在VS2013中工作)

此外,如果我将行
A*c=newa[]{
更改为
A*c=newa[4]{
,错误就会消失,一切正常

所以我的问题是: 为什么会有这些奇怪的数字?如果我不定义构造函数,数组中的A对象不会以某种方式正确构造吗?
为什么我需要显式指定数组大小,即使它在编译和链接时不会出错?以这种方式初始化堆栈上的数组不会给我一个运行时错误(我测试了它以确定)。

这是一个错误:

A* c = new A[] { {3}, {4}, {5}, {6} };
必须将维度放入
[]
中。使用
new
时,无法从初始值设定项列表推断数组维度

4
放在这里可以使您的代码正确地为我工作

您的编译器显然有一个“扩展”,它将
新A[]
视为
新A[1]

如果您在标准模式下编译(使用gcc或clang,
-std=c++14-pedantic
),这总是一个好主意,编译器会告诉您类似的事情。除非您确实确定警告不是错误,否则将警告视为错误:)

为什么会有奇怪的数字

因为没有为它们分配内存。指针指向Crom知道什么。该结构不应编译

如果我不定义构造函数,数组中的A对象不会以某种方式正确构造吗

如果没有构造函数,所有成员都将被初始化为默认值。
int
和大多数普通的旧数据类型都没有定义的默认值。在典型的实现中,它们会得到分配的内存块中已经存在的值。如果成员对象的类型不是默认构造函数,并且无法做一个,你会得到一个编译器错误


为什么我需要显式地指定数组大小,即使它可以编译和链接,而不需要指定

它不应该编译,数组的大小(未指定且自身存在错误)与初始值设定项列表中的元素数不匹配,因此编译器存在错误。此时不涉及链接器

以这种方式初始化堆栈上的数组不会给我一个运行时错误(我测试了它以确保)

在静态版本中,编译器可以计算初始化列表中的元素数。为什么使用new的动态版本不能,我得说我没有好的答案。你可能会认为这只是简单地计算初始化列表,所以有更深层的原因阻止它。辩论并批准该标准的人要么从不使用c考虑过以这种方式分配动态数组,或者找不到一种好的方法使其在所有情况下都能工作。同样的原因,可变长度数组仍然不在标准中


“为什么我需要显式地指定数组大小,即使它可以编译和链接,但不需要?它不应该编译,…。”要明确的是:如果我将构造函数添加到并运行它,它将在删除[]之前正常运行语句。只有这样它才会崩溃,但如果在堆上分配数组,您是否需要指定数组的大小。您分配的是指针(例如
a*
)而不是数组。从中读取会调用未定义的行为。它甚至无法编译!奇怪的数字是因为您的编译器有点崩溃。g++5.1说“错误:在']'标记之前应为主表达式”和“错误:“A[1]”的初始值设定项太多”。VS 2015表示“错误C3078:必须在新表达式中指定数组大小。”“.VS2013对该代码的理解尚不清楚。要学究化,您只需使用能够识别该选项的gcc或clang版本的
-std=c++11
。您不需要升级到c++14,也不需要
-pedantic
。clang(正确地)拒绝使用
新的[]{…}”
因为,根据标准,方括号内应该有一个表达式。gcc对
新A[]
并不犹豫,因为它将其解释为
新A[1]
。但是,它对三个额外的初始值设定项犹豫。“为什么我需要显式地指定数组大小,即使它可以编译和链接,但没有?它不应该编译,…。”要明确的是:如果我将构造函数添加到并运行它,它在delete[]语句之前运行得很好。只有这样它才会崩溃,但它不会崩溃,这是:”如果没有构造函数,所有成员都将被初始化为默认值。int和大多数普通的旧数据类型没有定义的默认值。“。对于结构,用户定义的ctor似乎是可选的,因为您可以通过提供与其数据字段对应的参数来初始化结构。@BitJunky无法在注释中正确回答这些参数。请将它们添加到答案中。”。
A* c = new A[] { {3}, {4}, {5}, {6} };
A* c = new A[]