下面的代码是否会正确地初始化从中返回的内存malloc?
#include <cstdlib>
#include <new>
int main()
{
char* p = new (std::malloc(10)) char[10]{};
}
Run Code Online (Sandbox Code Playgroud)
是的,{}只要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');
}
Run Code Online (Sandbox Code Playgroud)
该程序将运行并打印任何内容,因为初始化显式清除了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[](std::size_t, void*)和其他放置分配函数的那些表达式.开销的数量可能因新的一次调用而异.
换句话说,如果您new对单个对象使用放置,一切都很好并且没有插入的开销,但是如果您通过放置分配数组new,则可能存在开销,并且从调用到调用的大小可能不同.
这是一个非常非常糟糕的主意.
目前,new与所有数组new表达式一样,放置数组允许添加未指定数量的开销.程序没有可移植的方法来知道这个开销有多少字节.
因此,除非实现的数组分配开销char[10]为零,否则您的代码具有未定义的行为.
如果指针指向足够的内存以容纳所有数组元素加上未指定的开销量(这是一个非常大的if,因为没有可移植的方式让你确定),那么表达式确实会对内存进行零初始化.