含未初始化字段的对象能否加入std::vector?编译器分歧解析
哪个C++编译器的行为符合标准?
我们来看这段C++代码:
#include <vector> struct A { constexpr A() noexcept {} int v; }; constexpr bool f() { std::vector<A> as; as.reserve(1); as.emplace_back(); return true; } static_assert( f() );
这段代码中,结构体A的默认构造函数未初始化成员变量v,我们在常量表达式中通过std::vector<A>::emplace_back()构造A对象,并用static_assert验证表达式结果。
不同编译器的表现存在差异:
- MSVC编译器会报错,错误信息如下:
<source>(14): error C2131: expression did not evaluate to a constant <source>(11): note: failure was caused by a read of an uninitialized symbol <source>(11): note: see usage of 'A::v'
- GCC与Clang均可正常编译该程序。
结论
GCC和Clang的行为符合C++标准,MSVC的报错不符合标准要求。
原因解析
根据C++标准,常量表达式求值过程中,只有实际读取未初始化对象的值时,才会导致表达式不满足常量表达式的要求。而在这段代码中:
- 我们仅构造了
A对象,但全程没有读取A::v的值——函数f()最终仅返回true,没有任何访问v的操作。 std::vector的reserve操作和emplace_back构造对象的过程中,标准并未要求必须读取未初始化的成员变量,此处的默认构造仅完成对象的构造,并未触发对v的读取。
MSVC错误判定构造A的过程中存在对未初始化v的读取,但实际上不存在这样的操作,因此其报错不符合标准。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

