未加cont修饰的左值引用不能绑定到右值
目录
一、问题背景
二、错误分析
三、警告分析
一、问题背景
在initial value of reference to non-const - C++ Forum看到如下有问题的代码,编译如下代码看看
#include <iostream>
#include <cmath>int g(double x) { return std::floor(x); }
int&& i(double x) { return g(x); }void Do_Type_deduction()
{auto& li = i(8.8);
} int main()
{Do_Type_deduction();std::cout<<"exit"<<std::endl;return 0;
}
g++编译
test.cpp: In function ‘int&& i(double)’:
test.cpp:5:29: warning: returning reference to temporary [-Wreturn-local-addr]5 | int&& i(double x) { return g(x); }| ~^~~
test.cpp: In function ‘void Do_Type_deduction()’:
test.cpp:9:17: error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’9 | auto& li = i(8.8);| ~^~~~~
cpp.sh中编译
main.cpp:5:28: warning: returning reference to local temporary object [-Wreturn-stack-address]
int&& i(double x) { return g(x); }^~~~
main.cpp:9:11: error: non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'auto& li = i(8.8);^ ~~~~~~
1 warning and 1 error generated.
二、错误分析
error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’和error: non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'的含义是一样的。代码第9行中的i(8.8)返回的是int的右值引用。li类型会被推导为int&类型,是一个未加const的左值引用。c++语法规定,未加const的左值引用是不能绑定到右值的,所以第9行报错。这一条规则也是c++类拷贝构造函数和类赋值运算符重载函数的形参要加const修饰的理由,因为从右值对象拷贝构造新对象和从右值对象赋值到目标对象的需求是存在的。
c++类拷贝构造函数和类赋值运算符重载函数的形参为什么要加const?-CSDN博客
所以只需将第9行改成const auto&li = i(8.8);编译报错即可解决。
三、警告分析
再来看代码第5行的警告。
在代码中,函数i被定义为返回一个右值引用int&&。g(x)调用返回的是一个int类型的临时对象(右值)。右值引用通常用于绑定到临时对象,并且允许对这些临时对象进行移动操作。但是不能直接将一个临时对象的右值引用返回,因为当函数返回时,这个临时对象的生命周期就结束了,返回的右值引用将变成一个悬空引用,指向一个已经被销毁的对象,这会导致未定义行为。
在c++中,函数返回右值引用时,通常是为了移动语义,即返回一个对象的所有权,但前提是这个对象的生命周期要能够延长到函数外部。而这里g(x)返回的是一个临时值,它的生命周期在i函数返回时就结束了。