求解C++常量左值引用为什么可以绑定一个右值

uouo88 2019-08-27 01:10:30
如题,正常情况下引用代表变量的一个别名,如:
int a = 1;
int &b = a; //ok(b是a的一个别名,两者指向相同的内存地址)
int &c = 2;//error(不能将非常量左值引用绑定到右值2)
const int &d = 3;//ok(为什么常量左值引用却可以绑定到右值3?)


求大神解答!
...全文
604 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
csucxy 2019-08-28
  • 打赏
  • 举报
回复
很抱歉!我上面写的示例程序,在VS和DEV C++中的运行结果其实是一样的,之所以开始说不一样是因为我没有注意到64位与32位。特此说明。 楼主提到的C++的引用在编译器底层实现,有很多朋友通过反汇编等方式进行了分析验证,但我目前确实也没有在ISO C++以及类似权威的依据中找到相应阐述,如果有哪位朋友找到了相应的证据,请告知我,不甚感激。 当然,本人也认为这是一种底层实现的方式,但目前不能排除其它方式的可能。
uouo88 2019-08-28
  • 打赏
  • 举报
回复 1
csucxy的推测是正确的,我查了相关的资料如下,当一个临时变量(右值)被用来初始化一个引用的话,那这个临时变量的生命周期就会被延长,直到引用被销毁,从而不会因此产生悬空(dangling)的引用。并且通过使用这个技巧,在一个域内使用多态时,可以避免使用指针!详见下面文章:

https://www.cnblogs.com/catch/p/3251937.html
ZPJFCCZGZ 2019-08-28
  • 打赏
  • 举报
回复
这样理解会不会好一点:使用引用是为了去改变被引用的变量: 在int &c = 2中,原意是想引用c去改变右值,而右值是一个常量,不能改变,所以错误了,如果右值是一个变量,就可以: 而这个const int &d = 3中,左值直接定义成了常变量,原意就是只是想引用右值,而不想改变右值,所以右值可以直接用整数。
csucxy 2019-08-27
  • 打赏
  • 举报
回复
引用的底层实现,标准没有规定,编译器当然可以如你所说的方式来实现(事实上可能很多编译器也是这么做的),也可以不这样。 如下程序,用VS编译,运行结果如你所说,然后用DEV C++运行结果则不同。 #include <iostream> using namespace std; class T { public: T(char c) :rc(c) {} ~T() = default; private: char& rc; }; int main() { char cc = 'A'; T t(cc); cout << sizeof(t); return 0; } 当然,也许我这个测试并不是你所认为的正确方式。 如3+3这类表达式,我们都知道其内存空间称之为临时内存空间,一般情况下会在使用后自动回收。但这个回收的时间并不是表达式计算完“立刻”执行,否则也就无法使用该表达式的值了——当然这一点也并不能说明你的疑问。问题的关键估计是(我没找到权威依据,即个人推测),在这种情况下,该表达式的内存空间的回收会延后到引用的生存期之后,以保证该引用在其生存内始终是有效的。 至于int& r=3+3;到底有没有意义,个人觉得这类型引用似乎用处不大。
uouo88 2019-08-27
  • 打赏
  • 举报
回复
引用 4 楼 taodm 的回复:
因为“规定”啊。所谓标准,就是不停妥协,不停打补丁的结果。

额~无力反驳~
uouo88 2019-08-27
  • 打赏
  • 举报
回复 1
引用 5 楼 csucxy 的回复:
引用是引用,地址是地址,不是一码事。一个常量或者一个如你写的3+3这样的表达式,它也是要分配内存空间,也是有值的,所以常引用可以做为它们的别名,以代表它们。尽管像3+3这样的表达式的内存空间我们常说是一个临时的内存空间。

引用的背后也是用指针实现的,sizeof一个内含引用成员的class可以发现大小正好为4,即一个指针的大小,所以整型常量引用就类似于int * const p这样的一根指针,
3+3这样的表达式所代表的临时对象是一个右值,右值不具有持久性,理论上应该在该行赋值语句结束后空间就自动销毁了,那绑定到引用常量左值引用还有什么意义呢?
csucxy 2019-08-27
  • 打赏
  • 举报
回复
引用是引用,地址是地址,不是一码事。一个常量或者一个如你写的3+3这样的表达式,它也是要分配内存空间,也是有值的,所以常引用可以做为它们的别名,以代表它们。尽管像3+3这样的表达式的内存空间我们常说是一个临时的内存空间。
taodm 2019-08-27
  • 打赏
  • 举报
回复
因为“规定”啊。所谓标准,就是不停妥协,不停打补丁的结果。
  • 打赏
  • 举报
回复
引用 2 楼 uouo88 的回复:
[quote=引用 1 楼 zjq9931 的回复:] 因为const int &d是常量啊。引用的也是常量,不能修改的值啊。 int &c不是常量必须要引用一个可以修改的变量,代码里面却引用一个常量,不能修改的值,肯定错误啊。
大佬你好,谢谢你的回答,不过有一点我还是不太明白,右值不是一个变量名,哪儿来的变量地址给左值引用去绑定呢?比如const int &e = 3 + 3;后面的这个是个算术表达式,只是一个临时的计算结果。[/quote] 调试运行,看汇编代码
uouo88 2019-08-27
  • 打赏
  • 举报
回复 1
引用 1 楼 zjq9931 的回复:
因为const int &d是常量啊。引用的也是常量,不能修改的值啊。

int &c不是常量必须要引用一个可以修改的变量,代码里面却引用一个常量,不能修改的值,肯定错误啊。


大佬你好,谢谢你的回答,不过有一点我还是不太明白,右值不是一个变量名,哪儿来的变量地址给左值引用去绑定呢?比如const int &e = 3 + 3;后面的这个是个算术表达式,只是一个临时的计算结果。
  • 打赏
  • 举报
回复
因为const int &d是常量啊。引用的也是常量,不能修改的值啊。 int &c不是常量必须要引用一个可以修改的变量,代码里面却引用一个常量,不能修改的值,肯定错误啊。

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧