通过将std :: tuple <int,int>赋值给const std :: tuple <int,int>&来延长它的生命周期

Mes*_*kon 5 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";
}
Run Code Online (Sandbox Code Playgroud)

这似乎20在所有主要编译器上编译和打印.这两种类型的标准是否符合或未定义的行为是不同的?我知道可以通过分配它来延长临时的生命周期const T&,但据我所知,std::tuple<int&, int>它的类型不同std::tuple<int, int>.

Nat*_*ica 8

这是明确定义的行为.

const std::tuple<int, int>& t = f();
Run Code Online (Sandbox Code Playgroud)

没有给你一个你创建的元组的引用,f()因为它们有不同的类型.相反,发生的事情是std::tuple<int, int>f()返回创建临时,然后临时绑定t.由于这是一个副本,因此您可以获得该i时间点的值,并且不再与之相关联.

你用过的吗?

const std::tuple<int&, int>& t = f();
Run Code Online (Sandbox Code Playgroud)

然后21会被打印,因为你仍然会i在元组中引用.


son*_*yao 6

这不是UB.

但据我所知,std::tuple<int&, int>它的类型不一样std::tuple<int, int>.

是的,引用不能直接绑定到不同类型的对象.考虑const std::tuple<int, int>& t = f();,返回的std::tuple<int&, int>将被转换std::tuple<int, int>隐式,这是一个临时的std::tuple<int, int>.然后临时绑定t并将生命延长到生命周期t.