C++ msvc的动态数组初始化行为不同于gcc和clang

C++ msvc的动态数组初始化行为不同于gcc和clang,c++,gcc,visual-c++,clang,c++17,C++,Gcc,Visual C++,Clang,C++17,给定类型 struct S { int x; }; 和两个功能 S* f() { const auto x = new S[1] { { 42 } }; return x; } S* g() { const auto x = new S[1]; x[0] = {42}; return x; } 人们会认为f和g的行为是相同的。根据f应在x上执行聚合初始化,这将导致相同的行为。看看clang和gcc的组合,这似乎是正确的,f和g生成了完全相同

给定类型

struct S
{
    int x;
};
和两个功能

S* f()
{
    const auto x = new S[1] { { 42 } };
    return x;
}

S* g() 
{
    const auto x = new S[1];
    x[0] = {42};
    return x;
}
人们会认为
f
g
的行为是相同的。根据
f
应在
x
上执行聚合初始化,这将导致相同的行为。看看clang和gcc的组合,这似乎是正确的,
f
g
生成了完全相同的组合

然而,我想msvc并不想这么做。对于
g
而言,msvc的组装类似于clang和gcc,但对于
f
而言,它似乎完全忽略了初始值设定项:

S * f(void) PROC                                    ; f, COMDAT
        mov     ecx, 4
        jmp     void * operator new[](unsigned __int64)                     ; operator new[]
S * f(void) ENDP                                    ; f

S * g(void) PROC                                    ; g, COMDAT
$LN4:
        sub     rsp, 40                             ; 00000028H
        mov     ecx, 4
        call    void * operator new[](unsigned __int64)               ; operator new[]
        mov     DWORD PTR [rax], 42                 ; 0000002aH
        add     rsp, 40                             ; 00000028H
        ret     0
S * g(void) ENDP                                    ; g
奇怪的是,如果我们用
int
替换
S
,msvc将执行初始化,但也会添加一些额外的指令(我不明白,也许有人也可以对此进行说明)

这是一个完整的例子

在这种情况下,标准合规行为是什么?如果我们将
S
替换为
int
),那么
f
中的附加装配说明在做什么

编辑
已报告错误,并且可以跟踪

对于添加的附加指令,我不确定它为什么要更改堆栈指针,这似乎很无用;但是
测试rax,rax;je短$LN3@f
是为了确保在
new[]
失败时不会尝试初始化。看起来像
msvc
错误。你应该给他们一个反馈。
int * f(void) PROC                                 ; f, COMDAT
$LN6:
        sub     rsp, 40                             ; 00000028H
        mov     ecx, 4
        call    void * operator new[](unsigned __int64)               ; operator new[]
        test    rax, rax
        je      SHORT $LN3@f
        mov     DWORD PTR [rax], 42                 ; 0000002aH
        add     rsp, 40                             ; 00000028H
        ret     0
$LN3@f:
        add     rsp, 40                             ; 00000028H
        ret     0
int * f(void) ENDP                                 ; f