为什么通过条件运算符将引用传递给初始化列表会导致警告?

Why does passing a reference through a conditional operator to an initializer list lead to a warning?

以下代码导致此警告(vc 和 gcc -Wextra):

warning C4413: 'ReferencingContainer::_vector' : reference member is initialized to a temporary that doesn't persist after the constructor exits

但我不明白为什么。我以为我只是路过引用

#include <vector>

struct Referencing
{
    Referencing(int const &x) : _x(x) {}
    Referencing(int const &x, int dummy) : _x(x > 5 ? x : throw "error") {} // bad code, warning is ok

    int const &_x;
};

struct Container
{
    std::vector<double> _vector;
};

struct ReferencingContainer
{
    ReferencingContainer(Container const &container)
        : _container(container)
        , _vector(container._vector.size() > 0 ? container._vector : throw "error")  // <-- warning occurs here
    {}

    Container const &_container;
    std::vector<double> const &_vector;
};

int main()
{
    Referencing test1(21);
    Referencing test2(22, 0);

    Container container;
    ReferencingContainer referencingContainer(container);

    return 0;
}

为什么编译器对我的代码不满意?我真的需要担心我的对象会引用一个临时对象吗?

如果您添加 Wextra 标志,您将收到此警告:

px.cpp:12:83: warning: a temporary bound to ‘ReferencingContainer::_vector’ only persists until the constructor exits [-Wextra]
         , _vector(container._vector.size() > 0 ? container._vector : throw "error") // <--- warning occurs here!

这是编译器的一个bug,根据这个问题:

Spurious warning about binding temporary to reference member in constructor

然而,正如 vsoftco 指出的那样,该警告在 5.1 版中仍然存在

其他相关问题:

  1. C++ constructor: garbage while initialization of const reference
  2. Does a const reference prolong the life of a temporary?

一个可能的快速解决方法是从 ?: 表达式中传递一个指针,然后取消引用它。

, _vector(*(container._vector.size() > 0 ? &container._vector : throw "error"))

那么这里的问题是什么?

编译器告诉你,平时他们对我们很有礼貌。根据 std::vector::size 的引用,我们有:

size_type size() const;

这意味着当您在它创建警告的行中调用它时,size() 将 return a copy[= _vector 大小的 49=],当构造函数超出范围时,它将超出范围。