为什么在使用 auto&&it=--vec.end(),是 UB 时自动推导左值引用?

why does auto deduce lvalue reference when using auto&&it=--vec.end(),is it UB?

本文关键字:UB 引用 auto it 为什么 end --vec      更新时间:2023-10-16

请参阅下面的代码片段:

#include<vector>
using std::vector;
int main()
{
vector<int> a;
auto &&it=--a.end();//what?the hint tell me it deduces a lvalue reference type!
}

我们都知道,当操作数本身是右值时,带有operator --的自定义类会返回一个xvalue,例如--Myclass().显然Myclass()prvalue,所以--Myclass()的返回值也应该是rvalue(prcisely,xvalue)。
来自CPPREF

a.m,对象表达式的成员,其中 a 是右值,m 是非引用类型的非静态数据成员;

那么,为什么auto在这种情况下推导出右值参考呢? 更重要的是,代码片段可以编译而没有任何错误!

为什么右值可以绑定到右值引用?

而且我遇到了一个令人困惑的错误(和上面的代码片段不一样,我确定向量不为空):后来当我使用it时,发生了段错误

导致分段错误的代码(在最后三行) 此代码是中文在线测试 PAT 的答案,当我提交答案时,它会引起分段错误。

使用左值引用绑定--Myclass(),并在以后使用它是否是未定义的行为

我们都知道,当我们编写类似operator ----Myclass()

不,这不是我们所知道的。从技术上讲,用户定义的前缀递减运算符可以返回对象或引用。实际上,前缀递减运算符通常返回左值引用。

显然Myclass()是 prvalue,所以--Myclass()的返回值也应该是 prvalue。

这不是价值类别的传播方式。您可以在 prvalue 上调用函数,该函数可以返回一个左值(可能返回*this)。

那么,为什么在这种情况下自动推导出左值参考呢?

因为迭代器的递减运算符返回一个左值引用。


使用auto it来解决问题。


使用左值引用绑定--Myclass(),并在以后使用它是否是未定义的行为?

取决于如何声明Myclass::operator--()。如果它返回一个左值引用,那么那就是 UB。如果它返回一个对象,则没有 UB。可以提供由 ref 限定符重载的两个变体。

这是一个"通用参考"。变量不是右值引用,而是右值移动到其中的左值。这是必要的,因为引用不会延长临时对象的生存期。