初始化数组时使用(或不使用)括号

Posted

技术标签:

【中文标题】初始化数组时使用(或不使用)括号【英文标题】:Using (or not using) parentheses when initializing an array 【发布时间】:2015-07-02 13:47:18 【问题描述】:

在我正在阅读的 c++ 代码中,有一些初始化为类似的数组

int *foo = new int[length];

还有一些喜欢

int *foo = new int[length]();

我的快速实验无法发现这两者之间有任何区别,但它们是并排使用的。

有区别吗,如果有呢?

编辑;因为有一个断言,第一个应该给出不确定的输出,所以这里是一个显示可疑数字 0 的测试;

[s1208067@hobgoblin testCode]$ cat arrayTest.cc
//Test how array initilization works
#include <iostream>
using namespace std;
int main()
int length = 30;
//Without parenthsis
int * bar = new int[length];
for(int i=0; i<length; i++) cout << bar[0] << " ";

cout << endl;
//With parenthsis 
int * foo = new int[length]();
for(int i=0; i<length; i++) cout << foo[0] << " ";


cout << endl;
return 0;

[s1208067@hobgoblin testCode]$ g++ arrayTest.cc
[s1208067@hobgoblin testCode]$ ./a.out
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[s1208067@hobgoblin testCode]$ 

编辑 2;显然这个测试有缺陷,不要相信它 - 查看详细答案

【问题讨论】:

没有区别,只是调用了不带参数的构造函数 @celticminstrel,您正在打印一个值初始化的int。相同的语法并不意味着它具有默认构造函数。 (作为参考,表达式 T(),其中 T 是非数组完整对象类型或(可能是 cv 限定的)void 类型的简单类型说明符或类型名称说明符,创建指定类型,其值是通过值初始化 (8.5) 类型 T 的对象产生的值;对于 void() 情况不进行初始化。) 见 Do the parentheses after the type name make a difference with new? 这是案例 A,在 C++11 中也是如此。 我从未真正见过数组初始化的括号。 @nilo,是的,您可以认为它们是具有构造函数的特殊非类类型。不幸的是,它并不总是如此一致。您会期望 int x; 使用“默认构造函数”并且 int x = int(); 也使用默认构造函数,因为当您将 int 替换为合适的用户定义类型时会发生这种情况。然而,他们实际上做不同的事情。我想更好的类比是struct S int x;; 在执行S s;S s = S(); 时的行为,尽管它与普通的int 案例一样直观。 【参考方案1】:

这一行default-initializeslengthints,也就是说你会得到一堆值不定的ints:

int *foo = new int[length];

这条线value-initializes他们,所以你得到全零:

int *foo = new int[length]();

【讨论】:

在快速实验中,两者似乎都只有 0。这只是第一个版本的机会吗? @Jekowl,是的,在第一种情况下打印它们是未定义的行为。 不确定并不意味着“非 0”。它的意思是“可以是任何东西”。让它们碰巧为 0 是可以接受的,但不是你应该依赖的。 在标准下当然可以接受,但看起来它正在以两种方式进行零初始化...... @Jekowl 你接受你认为对你帮助最大的答案——你不必解释它。我不会把它当作个人的:)【参考方案2】:

使用括号保证数组的所有元素都初始化为0。我只是尝试使用以下代码:

#include <iostream>
using namespace std;

int main(int,char*[])
    int* foo = new int[8];
    cout << foo << endl;
    for(int i = 0; i < 8; i++)
        foo[i] = i;
    delete[] foo;
    foo = new int[8];
    cout << foo << endl;
    for(int i = 0; i < 8; i++)
        cout << foo[i] << '\t';
    cout << endl;
    delete[] foo;
    foo = new int[8]();
    cout << foo << endl;
    for(int i = 0; i < 8; i++)
        cout << foo[i] << '\t';
    cout << endl;
    delete[] foo;
    return 0;

当我编译并运行它时,看起来foo 每次都分配在同一个内存位置(尽管你可能不能依赖它)。对我来说,上述程序的完整输出是:

0x101300900
0x101300900
0   1   2   3   4   5   6   7   
0x101300900
0   0   0   0   0   0   0   0

因此,您可以看到foo 的第二次分配没有触及分配的内存,使其处于与第一次分配时相同的状态。

【讨论】:

以上是关于初始化数组时使用(或不使用)括号的主要内容,如果未能解决你的问题,请参考以下文章

初始化我的数组时出错

Java数组的创建和初始化

Java数组的创建和初始化

多维数组

差异方法初始化char数组

关于多维数组的注意事项