关于const reference的疑惑

囧豆粉 2011-06-08 10:35:04
C++中const reference的奇怪问题

在<C++ Primer>第四版中说,const Reference is a Reference To const (P.60)。

而这里有种情况:

int i = 2000;

const int &refI = i; //i不是const,但refI是。

++i;

程序输出的结果,refI的值为2001.也就是说, refI的值被通过另一种途径(++i)改变了。这种写法与“const Reference is a Reference To const”的说法相悖。而且,明明是const,却被改变了,有点。。。

用的是gnu c++编译器= =。至于微软的编译器,还没有测试过。。。

这种情况书上并没有提到,既没有否认也没有肯定这种写法的正确与否。

书上倒是给了另一种情况:

double dval = 3.14;

const int &ri = dval;

经测试,在这种情况下,对dval的值的改变并不影响ri的值。(书上对此没有明确的说明)

因为这种情况实际相当于--


double dval = 3.14;

int temp = dval;

const int &ri = temp;


跟ri有关系的,只有temporary variable而已,这东西在使用完毕大概就销毁了(应该说是不可见才对?)

而如果把我所说的第一种情况改为

int i = 2000;

const int &refI = i+2; //i不是const,但refI是。

++i;

此时输出的refI的值为2002.

求问为什么会有这些差别。另外,我的第一种写法是否正确。
...全文
301 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
南京浪人甲 2011-06-09
  • 打赏
  • 举报
回复
总觉得没说明白,再举个例子:
比如你开车撞人了,警察要抓你。这时候,你如果说“我打电话给我爸,李刚!”,那么,警察就不敢抓你了。
但是如果说:“我打电话给我爸”,那么,你就被抓走了。
其实,“我爸”--非const变量
“我爸是李刚”--const变量
对别人喊的时候,就相当于--引用变量(对外) int &refI 或const int &refI
自己心里的,相当于--被引用变量(隐藏) i
1、心里想着“我爸是李刚”,喊出来“我爸”,没用,被抓走。

const int i = 2000;
int &refI = i;

2、反之,即使心里想的是“我爸”,喊出来的是“我爸是李刚”,即使你爸不是李刚,也不会被抓走。。。

int i = 2000;
const int &refI = i;


南京浪人甲 2011-06-09
  • 打赏
  • 举报
回复
就用lz的例子:

int i = 2000;
const int &refI = i; //i不是const,但refI是。
++i

1、引用就是被引用变量的别名。只要“被引用变量(i)”和“引用变量(refI)”二者其一“合法地”改变,那么另一个肯定就会变。
2、const 型引用又是一种特殊情况,如上面的例子,refI是绝对不能改变的,所以const 型引用是可以用常量进行初始化(或者是表达式)的,而非const型引用只能用相应类型的非const变量进行初始化。举几个例子:

int i = 2000;
const int &refI = i+2; //这样是可以的
++i;//这里refI绑定的是一个表达式,其与i无关,也就是i变化不能影响refI
/////////////////////////////////////////////////////////////////////
int i = 2000;
int &refI = i+2; //这样是错误的,refI不能这么初始化
++i;
/////////////////////////////////////////////////////////////////////
const int i = 2000;
int &refI = i;//这也是错误的,
/////////////////////////////////////////////////////////////////////
int &refI = 2000;错误


总结一下关键点:
1、“const型引用”可以用“非const型”进行初始化(绑定),反之不行。可以这么想,一旦使用引用,我们就好比把原来被引用的变量名(i)“隐藏”起来了,主要关注引用变量(refI),试想,如果原来的类型是const(const int i = 2000),而引用类型为非const(int &refI = i),如果这样可行,那么岂不是会有改变refI,从而非法改变i的风险;而反过来,(int i = 2000;cosnt &refI = i;)就不会有这样的风险了。
2、const型引用是很牛X的,因为他不会非法改变其被引用变量,所以被赋予了很多非const引用所没有的性质,这如楼主举得例子:

double dval = 3.14;
const int &ri = dval

南京浪人甲 2011-06-09
  • 打赏
  • 举报
回复
分都是浮云,学到东西才是最重要的啊!
囧豆粉 2011-06-09
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 shanki_pm 的回复:]
const型引用是很牛X的,因为他不会非法改变其被引用变量,所以被赋予了很多非const引用所没有的性质
[/Quote]
总结得很清楚,谢谢指教...
看样子const reference确实很强大,可以给一个对象创建一个副本(和原来的对象是同一个对象),但这个副本又没有修改这个对象的权限.只有通过其它途径修改这个对象才可以.

另外,抱歉结贴早了...没分给了...
jiangchaomr 2011-06-08
  • 打赏
  • 举报
回复
恩 临时变量的问题 学习了
囧豆粉 2011-06-08
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 supermegaboy 的回复:]
7.1.5.1 The cv-qualifiers
.............
A pointer or reference to a cv-qualified
type need not actually point or refer to
a cv-qualified object, but it is treated as
if it does; a const-qualified access path cannot be used to modify an object
even if the object referenced is a non-
const object and can be modified
through some other access path.
[/Quote]
原来是这么一回事~并不是说const就无法更改了,而是通过别的途径可以更改…
明白了~谢谢帮忙查证,也谢谢各位的耐心讲解~
飞天御剑流 2011-06-08
  • 打赏
  • 举报
回复
在C中,const的确是readonly,但在C++中,由于不再规定常量表达式必须是编译期的,因此继续把C++中的const仅仅视作readonly是不对的,此时一个const对象在表达式中就是一个常量表达式。那么const在C++中何时能视作readonly呢,当const作为类型派生的一部分时,例如楼主所举的例子,就可以视作readonly。
ryfdizuo 2011-06-08
  • 打赏
  • 举报
回复
const当初设计就是raedonly的等价。
const int& i = 4; const引用可以直接引用常量。。。
飞天御剑流 2011-06-08
  • 打赏
  • 举报
回复
在<C++ Primer>第四版中说,const Reference is a Reference To const (P.60)。
而这里有种情况:
C/C++ code
int i = 2000;
const int &refI = i; //i不是const,但refI是。
++i;
程序输出的结果,refI的值为2001.也就是说, refI的值被通过另一种途径(++i)改变了。这种写法与“const Reference is a Reference To const”的说法相悖。而且,明明是const,却被改变了,有点。。。
用的是gnu c++编译器= =。至于微软的编译器,还没有测试过。。。
这种情况书上并没有提到,既没有否认也没有肯定这种写法的正确与否。
-----------------------------------------------------------------------------------
摘录一段标准的内容给你看看,就会明白了:

7.1.5.1 The cv-qualifiers
.............
A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does; a const-qualified access path cannot be used to modify an object even if the object referenced is a non-const object and can be modified through some other access path.
guanzhouxuezi 2011-06-08
  • 打赏
  • 举报
回复
const引用可以绑定不同但相关的类型的对象或绑定到右值。
const引用表明该引用是不可改变的,如楼主的程序,如对ref1进行改变则会报错;
因为引用就是变量的别名,所以当变量改变,引用也自然就改变了。
nakedavril 2011-06-08
  • 打赏
  • 举报
回复
const 建议不要理解为常量,理解为只读
int i = 2000;
const int &refI = i;
++i;
//refI对i是只读的,只是可以通过这个别名来访问i的值,但不能修改他
至于这种写法的准确性,你下面的代码不就证明了么
int temp = dval;

const int &ri = temp;
ljt3969636 2011-06-08
  • 打赏
  • 举报
回复
第一句话是"cosnt可以引用const类型和非const类型"
ljt3969636 2011-06-08
  • 打赏
  • 举报
回复
cosnt引用const类型和非const类型,它只表示不能通过这个引用修改值,至于被引用的值是否被修改,引用就无能为力了。

另外你列举的2、3情况都是const应用可以引用中间变量造成的,而且这些中间变量都是匿名的,2你已经正确理解了

double dval = 3.14;
int &ri = dval ;//普通的非cosnt引用这样是不可以的,必须要求ri 和dval 类型一致,只有const才会产生那个中间变量,这个是const的特例!

3中refI引用到的是i+2的结果~~和i没什么关系
囧豆粉 2011-06-08
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 nakedavril 的回复:]
lz搞混了,第一种只是普通的const ref指向non const的变量,i变了,refI自然就变了和const ref指向literal 常量和其他不同的类型不是一回事
[/Quote]
呃,书上只是说A const reference can be initialized to an object of a different type or to an rvalue, such as a literal constant. 并没也提到当初值为一个对象时的具体情况,也没有说结果。倒是const reference能指向nonconst变量这点令人困惑,不是说const reference就是reference to const吗?
还是说,关于这点标准里有规定?
Ps:
我是不是钻死牛角尖了。。。

本人小白,第一次在CSDN发帖还望海涵。。。
nakedavril 2011-06-08
  • 打赏
  • 举报
回复
lz搞混了,第一种只是普通的const ref指向non const的变量,i变了,refI自然就变了和const ref指向literal 常量和其他不同的类型不是一回事
老规矩,先看本节效果图我们实现这个支付功能完全是借助小程序云开发实现的,不用搭建自己的服务器,不用买域名,不用备案域名,不用支持https。只需要一个简单的云函数,就可以轻松的实现微信小程序支付功能。核心代码就下面这些一,创建一个云开发小程序关于如何创建云开发小程序,这里我就不再做具体讲解。不知道怎么创建云开发小程序的同学,可以去翻看我之前的文章,或者看下我录制的视频:https://edu.csdn.net/course/play/9604/204528创建云开发小程序有几点注意的1,一定不要忘记在app.js里初始化云开发环境。2,创建完云函数后,一定要记得上传二, 创建支付的云函数1,创建云函数pay三,引入三方依赖tenpay我们这里引入三方依赖的目的,是创建我们支付时需要的一些参数。我们安装依赖是使用里npm 而npm必须安装node,关于如何安装node,我这里不做讲解,百度一下,网上一大堆。1,首先右键pay,然后选择在终端中打开2,我们使用npm来安装这个依赖。在命令行里执行 npm i tenpay安装完成后,我们的pay云函数会多出一个package.json 文件到这里我们的tenpay依赖就安装好了。四,编写云函数pay完整代码如下//云开发实现支付 const cloud = require('wx-server-sdk')cloud.init() //1,引入支付的三方依赖 const tenpay = require('tenpay'); //2,配置支付信息 const config = ;exports.main = async(event, context) => 一定要注意把appid,mchid,partnerKey换成你自己的。到这里我们获取小程序支付所需参数的云函数代码就编写完成了。不要忘记上传这个云函数。出现下图就代表上传成功五,写一个简单的页面,用来提交订单,调用pay云函数。这个页面很简单,1,自己随便编写一个订单号(这个订单号要大于6位)2,自己随便填写一个订单价(单位是分)3,点击按钮,调用pay云函数。获取支付所需参数。下图是官方支付api所需要的一些必须参数。下图是我们调用pay云函数获取的参数,和上图所需要的是不是一样。六,调用wx.requestPayment实现支付下图是官方的示例代码这里不在做具体讲解了,完整的可以看视频。实现效果1,调起支付键盘2,支付完成3,log日志,可以看出不同支付状态的回调上图是支付成功的回调,我们可以在支付成功回调时,改变订单支付状态。下图是支付失败的回调,下图是支付完成的状态。到这里我们就轻松的实现了微信小程序的支付功能了。是不是很简单啊,完整的讲解可以看视频。

64,671

社区成员

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

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