以下代码是否会正确地初始化从malloc
返回的内存?
#include <cstdlib>
#include <new>
int main()
{
char* p = new (std::malloc(10)) char[10]{};
}
答案 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]
的实现的数组分配开销为零,否则您的代码具有未定义的行为。
如果指针指向足够的内存以容纳所有数组元素加上未指定的开销量(如果因为那里没有可移植的方式,那就非常大了)可以肯定的是,表达式确实会对内存进行零初始化。