通过将std :: tuple <int&,int>分配给const std :: tuple <int,int =“”>&

时间:2019-01-18 14:15:16

标签: c++ language-lawyer

我正在使用std::tuple类,发现我说的是相当意外的行为。

考虑代码:

#include <iostream>
#include <tuple>

int i = 20;
std::tuple<int&, int> f() {
    return std::tuple<int&, int>(i, 0);
}

int main() {
    const std::tuple<int, int>& t = f();
    int j = ++i;
    std::cout << std::get<0>(t) << "\n";
}

这似乎可以在所有主要编译器上编译并打印20。该标准是符合标准还是未定义的行为,因为两种类型不同?我知道可以通过将临时变量分配给const T&来延长其使用寿命,但据我所知std::tuple<int&, int>std::tuple<int, int>的类型不同。

2 个答案:

答案 0 :(得分:8)

这是定义明确的行为。

const std::tuple<int, int>& t = f();

没有为您提供在f()中创建的元组的引用,因为它们具有不同的类型。取而代之的是从std::tuple<int, int>的返回中创建一个临时f(),然后将该临时绑定到t。由于这是一个副本,因此您将在该时间点获得i的值,并且不再与之耦合。

您使用过

const std::tuple<int&, int>& t = f();

然后将打印21,因为您仍然可以在元组中引用i

答案 1 :(得分:6)

这不是UB。

  

但据我所知std::tuple<int&, int>std::tuple<int, int>的类型不同。

是的,引用不能直接绑定到具有不同类型的对象。给定const std::tuple<int, int>& t = f();,返回的std::tuple<int&, int>将隐式地从convertedstd::tuple<int, int>,这是一个临时的std::tuple<int, int>。然后将临时绑定到t,并将生存期延长到t的生存期。