条件运算符结果赋值复制后移动:MSVC行为是否符合C++标准?
MSVC编译条件表达式初始化代码报错是否符合C++标准?
简化后的测试程序
struct S { S() {} S(const S &) {} S(S &&) = delete; }; S x; S y = false ? S() : x;
编译结果差异
- GCC和Clang可正常编译该程序
- 最新版Visual Studio 2022 v17.10编译报错,错误信息:
error C2280: 'S::S(S &&)': attempting to reference a deleted function
观察到的行为差异:MSVC会先将x复制到临时对象,再尝试将该临时对象移动到y;而GCC、Clang不会调用被删除的移动构造函数S(S &&)。
结论:MSVC的行为不符合C++标准
根据C++标准的相关规定:
- 条件表达式
false ? S() : x的结果值类别应为左值:因为分支中一个是右值(S())、一个是左值(x),且右值分支可转换为左值分支的const S&类型,因此条件表达式的结果是左值。 - 用该条件表达式初始化
y属于直接初始化场景,编译器应直接利用条件表达式的结果构造y,调用复制构造函数S(const S&)即可完成初始化,完全不需要创建临时对象再执行移动操作。 - 即使不考虑复制消除,标准也不要求在此场景下生成临时对象并触发移动构造——MSVC的额外移动操作不符合标准对条件表达式值类别和初始化流程的定义。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

