当前位置: 首页 > news >正文

未加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函数返回时就结束了。


http://www.mrgr.cn/news/91297.html

相关文章:

  • 什么是3D视觉无序抓取?
  • 深入探索 C++17 中的 std::hypot:从二维到三维的欧几里得距离计算
  • Day4 25/2/17 MON
  • deepseek本地部署方案(超简单)
  • GPT-4o悄然升级:能力与个性双突破,AI竞技场再掀波澜
  • ping6 命令介绍和 IPv6 常见的网段划分
  • 想要追踪一个在传送带上运动的东西,该怎么选择工业相机呢,需要考虑哪些因素
  • Linux相关概念和易错知识点(28)(线程控制、Linux下线程的底层)
  • 【在时光的棋局中修行——论股市投资的诗意哲学】
  • Java 运行时常量池笔记(详细版
  • 【深度学习】环境和分布偏移
  • 【vmware虚拟机安装教程】
  • 用deepseek学大模型03-数学基础 概率论 最大似然估计(MLE)最大后验估计(MAP)
  • pptx文档提取信息
  • ROS基本功能
  • 大话风险-风险模型监测三道防线
  • C# windowForms 的DataGridView控件的使用
  • 电解电容的参数指标
  • 嵌入式硬件篇---OpenMV的硬件流和软件流
  • P9853 [入门赛 #17] 方程求解