使用值初始化数组对数据进行零初始化

时间:2015-04-17 19:19:03

标签: c++ c++11

以下代码是否会正确地初始化从malloc返回的内存?

#include <cstdlib>
#include <new>

int main()
{
    char* p = new (std::malloc(10)) char[10]{};
}

2 个答案:

答案 0 :(得分:7)

是的,只要{}在展示位置malloc内没有失败,它就会因为行尾的new而对内存进行零初始化。这是一个替代版本,更完整地证明了这一点。

#include <iostream>
#include <cassert>
#include <new>

char mongo[10];

int main()
{
    for (int i=0; i < 10; ++i)
        mongo[i] = 'a';
    char *p = new (mongo) char[10]{};
    for (int i= 0; i < 10; ++i)
        assert(p[i] == '\0');
}

此程序将运行并且不打印任何内容,因为mongo初始化显式清除了p数组(p别名)。相反,如果我们省略该行末尾的{},程序将断言并终止。

请注意,在使用malloc的版本中,您必须明确销毁对象 - 这是展示位置new带来的责任的一部分,而且是现代的几次C ++,其中必须明确地调用析构函数。

如果您在特定情况下使用malloc()分配内存,则必须发出相应的free(p),否则您的程序将泄漏内存。

房间里的大象

(谢谢,@ TC,指的是灰色的东西!)以下是标准的解释和示例(第5.3.4节):

  

示例:

     

new T会调用operator new(sizeof(T))

     

new(2,f) T会调用operator new(sizeof(T),2,f)

     

new T[5]会调用operator new[](sizeof(T)*5+x)

     

new(2,f) T[5]会调用operator new[](sizeof(T)*5+y,2,f)

     

这里,x和y是表示数组分配开销的非负未指定值; new-expression 的结果将从operator new[]返回的值中抵消此金额。此开销可应用于所有数组 new-expressions ,包括引用库函数运算符new[](std::size_t, void*)和其他放置分配函数的那些。开销的数量可能因新的一次调用而异。

换句话说,如果您对单个对象使用展示位置new,一切都很好,没有插入的开销,但如果您通过展示位置{{1}分配数组 ,可能有开销,从调用到调用甚至可能没有相同的大小。

答案 1 :(得分:5)

这是一个非常非常糟糕的主意。

目前,放置数组new与所有数组new表达式一样,允许添加未指定数量的开销。程序没有可移植的方法来知道这个开销有多少字节。

因此,除非char[10]的实现的数组分配开销为零,否则您的代码具有未定义的行为。

如果指针指向足够的内存以容纳所有数组元素加上未指定的开销量(如果因为那里没有可移植的方式,那就非常大了)可以肯定的是,表达式确实会对内存进行零初始化。