You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从花括号初始化列表直接初始化时的Copy-elision:哪个编译器正确?

关于C++初始化场景的标准合规性问题

在以下程序中,对象A a通过花括号初始化列表{A{}}完成直接初始化:

#include <iostream>

struct A {
    int v = 0;
    A() {}
    A(const A &) : v(1) {}
};

int main() {
    A a({A{}});
    std::cout << a.v;
}

MSVC和GCC编译运行后输出0,说明触发了拷贝消除(Copy-elision);而Clang输出1,执行了拷贝构造函数。

请问在此场景下,哪个编译器的行为符合C++标准?


回答

MSVC和GCC的行为符合C++17及以后版本的标准,Clang的行为不符合。

具体依据如下:

  • C++17及以后的标准明确规定:当用同类型的纯右值(比如代码中的A{}临时对象)初始化另一个同类型对象时,必须执行拷贝消除——编译器要直接在目标对象的内存位置构造该纯右值,完全跳过拷贝/移动构造函数的调用。
  • 对于A a({A{}})的场景,初始化器列表仅包含一个A类型的纯右值,根据列表初始化规则,这等效于用该纯右值直接初始化a,因此必须触发拷贝消除,最终a.v的值为默认构造的0。
  • Clang在此场景下未执行强制拷贝消除,反而调用了拷贝构造函数导致a.v变为1,不符合C++17及以后的标准要求。

若在C17之前的标准环境下,拷贝消除属于编译器可选的优化手段,此时三种编译器的行为都不违反标准。但当前主流编译器默认启用C17及以后标准,因此MSVC和GCC的行为是合规的。

内容的提问来源于stack exchange,提问作者Fedor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 10:03:22