为啥 int 数组在 C++ 中未初始化为零?

Posted

技术标签:

【中文标题】为啥 int 数组在 C++ 中未初始化为零?【英文标题】:Why is int array not initialized to zeros in C++?为什么 int 数组在 C++ 中未初始化为零? 【发布时间】:2012-08-04 23:15:12 【问题描述】:

我有一个 C++ 基本程序,它列出了给定数量的素数。完成工作的类如下 - 我的问题是,当“数量”的输入为 10 (特别是 10 - 它适用于我尝试过的所有其他数字)时,下面生成的数组未初始化为一个零数组。因此,“数组的最后一个元素为空”返回 false,我的代码无法正常运行。

我不知道我是否误解了,但是int数组不应该初始化为零吗?如果不是,整数 10 有什么特别之处导致它初始化为奇怪的值?

int* primecalc(int amount) 

int* primes = new (nothrow) int [amount];

//Throw an error if we can't allocated enough memory for the array.
if (primes==0) 
cout<< "Error allocating memory.";
return 0;


//Otherwise, start iterating through the numbers.
else 
primes[0] = 2;
primes[1] = 3;

int p = 2;

for (int i=4;primes[amount]==0;i++) 
int j = 0;
int k = 0;

    while ((primes[j]<=floor(i/2)) && !(primes[j]==0) && (k==0)) 

        if ((i % primes[j]) == 0) 
        k=1;
         
    j++;
     //end the while loop

if (k==0) 
        primes[p] = i;
        p++;



 //end the for loop

 //end the "else" part (this was only necessary in case memory could not be allocated)

return primes;

我也尝试不使用(nothrow),结果相同。提前感谢您的帮助!

【问题讨论】:

为什么要初始化新数组? 请注意,primes[amount]==0 会调用未定义的行为。 primes 的有效索引为 0 到 amount-1 @DanielFischer 啊,是的,我也应该解决这个问题。谢谢! 【参考方案1】:

int* primes = new (nothrow) int[amount]; 正在使用 default-initialization,对于像 int 这样的标量,这是一个 noop(即不执行实际初始化)。

如果您想要显式初始化,请改用 值初始化

int* primes = new (nothrow) int[amount]();

来自 C++11 标准,§8.5/6:

默认初始化T 类型的对象意味着:

如果 T 是一个(可能是 cv 限定的)类类型,则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化是非良构的); 如果T是数组类型,每个元素都是默认初始化的否则,不会执行初始化

如果程序调用 const 限定类型 T 的对象的默认初始化,T 应是具有用户提供的默认构造函数的类类型。

§8.5/7:

值初始化T 类型的对象意味着:

如果T 是具有用户提供的构造函数的(可能是 cv 限定的)类类型,则调用T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化是错误的) ; 如果 T 是一个(可能是 cv 限定的)非联合类类型,没有用户提供的构造函数,则对象为零初始化,如果 T 的隐式声明的默认构造函数是非微不足道,调用该构造函数。 如果T是一个数组类型,那么每个元素都是值初始化的否则,对象被零初始化

值初始化的对象被认为是已构造的,因此受本国际标准适用于“构造的”对象、“构造函数已完成的对象”等的规定的约束,即使没有调用构造函数用于对象的初始化。

§8.5/6:

零初始化T 类型的对象或引用意味着:

如果T是标量类型,则将对象设置为值0(零),取整型常量表达式,转换为T; 如果 T 是(可能是 cv 限定的)非联合类类型,则每个非静态数据成员和每个基类子对象都初始化为零,填充初始化为零位; 如果 T 是(可能是 cv 限定的)联合类型,则对象的第一个非静态命名数据成员初始化为零,填充初始化为零位; 如果T是数组类型,则每个元素都初始化为零; 如果T 是引用类型,则不执行初始化。

最后从 §8.5/10 开始:

初始化器为空括号集的对象,即(),应进行值初始化。

(所有重点都是我的。)

【讨论】:

【参考方案2】:

这样做只是为了提高效率。并非在所有情况下,数组都必须预先填充一个值,因此 C++ 默认情况下不会这样做。

如果你使用std::vector&lt;int&gt;而不是普通数组(我建议你这样做),你有一个构造函数来设置一个可以为0的初始值:

std::vector<int> v(10,0);  // 10 elements with 0

【讨论】:

为什么投反对票?虽然如果他们想要初始化就必须使用std::vector&lt;&gt; 的暗示是误导,但我在这个答案中看不到任何不正确 好吧,我也不理解反对意见,但 SF 似乎不是一门精确的科学。另外,我并不暗示使用向量进行初始化。我说 if OP 决定这样做。而且我推荐它不仅仅是为了初始化,而是为了更好的编程模式,所以谦虚地我没有看到这种误导。当然,添加一个带默认值的向量构造函数比在冗长而复杂的new 调用中添加一对括号要清楚得多,但这可能只是我的理解。

以上是关于为啥 int 数组在 C++ 中未初始化为零?的主要内容,如果未能解决你的问题,请参考以下文章

具有 char 数组的 C++ 结构以不寻常的方式初始化为零

在 C++ 中初始化动态二维数组

使用 memset 将结构体数组及其成员初始化为零

malloc()是否将分配的数组初始化为零?

c++ 指针基础问题 指针已经被初始化为NULL了,为啥还会出错?

Windows XP 会自动将数组初始化为零吗?