MSVC2013和新数组花括号初始化问题

3

我一直在查看这个小片段:

#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
}

gccclang正确输出0,但MSVC2013 Update 3输出1

我读过关于newnew-initializer5.3.4/17,但找不到任何证明MSVC行为合理的内容。

是否我遗漏了某些内容?这是已知的问题吗?


编辑:我附上了MSVC的内存转储和生成的汇编代码(x64 release

enter image description here

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)  

@user657267 这个可行并且正确地输出了0。 - Marco A.
@user657267,没错,它应该在标准的第5条和第8.5条左右。 - Marco A.
@HansPassant 在 -std=c++11 中,Clang 和 gcc 做了正确的事情。 - Marco A.
1
@HansPassant,C++11语法已经具有brace-or-equal-initializer语法。 - user657267
C++14有一个新规则,当初始化程序没有足够的元素时。引用:“如果在类定义中提供了花括号或等于初始值设定项,则其余成员将由它们的花括号或等于初始值设定项进行初始化;否则(自C++14起)通过空列表进行初始化,这执行值初始化”。我认为这适用于此处。 - Hans Passant
显示剩余9条评论
1个回答

2
这是MS VC++编译器的一个漏洞。根据C++标准(5.3.4 New),创建类型为T的新表达式将按以下方式初始化该对象:
- 如果省略了new-initializer,则对象将默认初始化(8.5);如果未执行任何初始化,则对象具有不确定值。 - 否则,new-initializer将根据直接初始化的初始化规则(8.5)进行解释。
并进一步说明(8.5.1 Aggregates):
- 如果列表中的初始化程序少于聚合体中的成员,则每个未显式初始化的成员都应从其brace-or-equal-initializer或(如果没有brace-or-equalinitializer)从空初始化程序列表(8.5.4)中初始化。
以及(8.5.4 List-initialization):
- 否则,如果初始化程序列表没有元素,则对象将值初始化
最后(8.5 Initializers):
- 对于类型为T的对象进行值初始化意味着 - 如果T是数组类型,则每个元素都将进行值初始化; - 否则,该对象将进行零初始化。
因此,数组的所有元素都应进行零初始化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接