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

huangapple go评论159阅读模式
英文:

Can an object with uninitialized fields be safely added in std::vector?

问题

在以下程序中,结构体 A 的默认构造函数未初始化其字段 v。然后,在一个常量表达式中,使用 A() 对象对 std::vector<A> 进行了emplace操作:

#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() );

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编译器都对该程序没有问题。在线演示:https://godbolt.org/z/addx11aTT

哪个编译器是正确的?

英文:

In the following program, default constructor of struct A does not initialize its field v. Then in a constant expression, std::vector&lt;A&gt; is emplaced with A() object:

#include &lt;vector&gt;

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

constexpr bool f() {
    std::vector&lt;A&gt; as;
    as.reserve(1);
    as.emplace_back();
    return true;
}
static_assert( f() );

MSVC compiler complains about the reading of uninitialized variable:

&lt;source&gt;(14): error C2131: expression did not evaluate to a constant
&lt;source&gt;(11): note: failure was caused by a read of an uninitialized symbol
&lt;source&gt;(11): note: see usage of &#39;A::v&#39;

But both GCC and Clang are fine with the program. Online demo: https://godbolt.org/z/addx11aTT

Which compiler is correct here?

答案1

得分: 1

看起来MSVC报告了一个读取错误。显然,通过评估然后丢弃emplace_back()返回的引用形式,而不仅仅是丢弃它。MSVC在一个简化版本中展示了一个bug。请参见下文。

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

这也可以通过以下方式看出,它创建了一个A对象,提供了对它的引用,然后,在评估引用时,在MSVC中引发了错误。它不应该这样,正如@user17732522在评论中指出的那样。它应该被丢弃为未使用的lvalue。

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

constexpr bool f() {
    A a;
    A& b = a;
    // b;   // 取消注释这一行会导致MSVC失败
    return true;
}
static_assert(f());

int main() {}

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

Message failure was caused by a read of an uninitialized symbol

这是一个MSVC的bug。

英文:

Looks like MSVC is reporting a read error. Apparently by evaluating then discarding the returned reference form emplace_back() rather than just discarding it. MSVC does demonstrate a bug in a simplified version. See below.

The problem isn't allocation in vector, it's that the emplace_back() is a method that returns an expression, a reference to the added element.

This can be also seen by the following which creates an A object, provides a reference to it, then, when the reference is evaluated it causes an error in MSVC. It should not, as @user17732522 pointed out in comments. It should be discarded as an unused lvalue.

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

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

int main() {}

Compiles fine but if the b, a reference to the objects is evaluated this error ensues:

Message		failure was caused by a read of an uninitialized symbol	

This is a MSVC bug.

huangapple
  • 本文由 发表于 2023年8月11日 05:07:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76879315.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定