可以将具有未初始化字段的对象安全地添加到 std::vector 中吗?

Fed*_*dor 8 c++ vector language-lawyer constexpr

在以下程序中,struct 的默认构造函数A不会初始化其字段v。然后在常量表达式中,std::vector<A>放置有A()对象:

#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() );
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

但 GCC 和 Clang 都对该程序很满意。在线演示: https: //godbolt.org/z/addx11aTT

这里哪个编译器是正确的?

dou*_*oug 1

看起来 MSVC 正在报告读取错误。显然,通过评估然后丢弃返回的参考表单,emplace_back()而不是仅仅丢弃它。MSVC 确实在简化版本中展示了一个错误。见下文。

问题不在于向量中的分配,而在于它emplace_back()是一个返回表达式的方法,即对添加元素的引用。

这也可以从下面的内容中看出,它创建了一个 A 对象,提供了对它的引用,然后,当评估该引用时,它会在 MSVC 中导致错误。正如@user17732522 在评论中指出的那样,它不应该。它应该作为未使用的左值被丢弃。

struct A {
    constexpr A() noexcept {}
    int v;
};

constexpr bool f() {
    A a;
    A& b = a;
    // b;   // uncommenting this causes MSVC to fail
    return true;
}
static_assert(f());

int main() {}
Run Code Online (Sandbox Code Playgroud)

编译正常,但如果b评估对对象的引用,则会出现此错误:

Message     failure was caused by a read of an uninitialized symbol 
Run Code Online (Sandbox Code Playgroud)

这是一个 MSVC 错误。