我一直在看这个小片段:
#include <iostream>
#include <cstring>
int main()
{
char const *a = "my string";
size_t len = strlen(a);
char *b = new char[len + 1]{0};
char *zeroes = new char[strlen(a) + 1];
memset(zeroes, 0, strlen(a) + 1);
std::cout << memcmp(b, zeroes, strlen(a) + 1); // 0 expected
}
gcc和clang正确输出0
,但MSVC2013更新3输出1
。
我看过关于5.3.4/17
和 new-initializer 的new
,但找不到任何证明MSVC行为的理由。
我错过了什么吗?这是一个已知的问题吗?
编辑:我从MSVC附加内存转储和生成的汇编代码( x64 release )
int main()
{
000007F676571270 push rbx
000007F676571272 sub rsp,20h
char const *a = "my string";
size_t len = strlen(a);
char *b = new char[len + 1]{0};
000007F676571276 mov ecx,0Ah
000007F67657127B call operator new[] (07F676571704h)
000007F676571280 mov rbx,rax
000007F676571283 test rax,rax
000007F676571286 je main+1Dh (07F67657128Dh)
000007F676571288 mov byte ptr [rax],0 // zero the first one out
000007F67657128B jmp main+1Fh (07F67657128Fh)
000007F67657128D xor ebx,ebx
char *zeroes = new char[strlen(a) + 1];
000007F67657128F mov ecx,0Ah
000007F676571294 call operator new[] (07F676571704h)
答案 0 :(得分:2)
这是MS VC ++编译器的错误。根据C ++标准(5.3.4新)
17创建类型为T的对象的new-expression初始化该对象,如下所示:
- 如果省略new-initializer,则默认初始化对象(8.5);如果没有执行初始化,则该对象具有不确定的值。
- 否则,根据8.5的初始化规则解释new-initializer以进行直接初始化。
进一步(8.5.1聚合)
7如果列表中的初始化子条款少于聚合中的成员,则未明确初始化的每个成员应从其大括号或等号初始化器初始化,或者如果没有大括号 - 或 - equalinitializer,来自空的初始化列表(8.5.4)。
和(8.5.4列表初始化)
- 否则,如果初始化列表没有元素,则该对象是值初始化的
最后(8.5个初始化者)
8对T类型的对象进行值初始化意味着
...
- 如果T是数组类型,则每个元素都是值初始化的; - 否则,对象被零初始化。
因此,数组的所有元素都应为零初始化。