我正在使用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>
的类型不同。
答案 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>
将隐式地从converted到std::tuple<int, int>
,这是一个临时的std::tuple<int, int>
。然后将临时绑定到t
,并将生存期延长到t
的生存期。