首先分析一段代码:

#include <bits/c++config.h>
#include <ostream>
#include <iostream>
#include <cstdio>
using namespace std;
class Node{
int x;
public:
Node(int x=):x(x){
} };
Node get(){
return Node();
}
int main(){
Node & i = get();
return ;
}

一点编译,输出一行编译错误

test1.cpp:25:21: error: invalid initialization of non-const reference of type ‘Node&’ from an rvalue of type ‘Node’

     Node & i =  get();

意思是不能将Node类型的右值复制给Node&类型的变量。

我尝试改一下源代码,主函数改为

 int main(){
2   //int & n = 5;
3 Node t = get();
4 Node & i = t ; 5
5   return ;
6 }

发现程序可以编译了。仔细对比这两段代码,我们可以得到这样一个事实:函数中返回的值相当于一个常量,它是临时产生的。只有当把这个函数的返回值赋值给变量的时候,我,们可以把变量的值赋值给Node&类型的变量。为了验证这个猜测,我们去掉上边的注释:

test1.cpp:24:15: error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of

 type ‘int’

     int & t = 5;


这个编译错误和上边的编译错误基本是一致的,从而验证了我们的猜测。

在这个问题的基础上,我们研究这样一个问题

 #include <bits/stdc++.h>
#include <istream>
using namespace std;
class Character{
char c;
public:
Character(){}
Character(char c):c(c){}
Character operator + (const int ch){
return Character(((c+ch-'a')%+)%+'a');
}
Character operator - (const int ch){
return Character(((c-ch-'a')%+)%+'a');
}
friend istream & operator >> (istream &is, Character &ch);
friend ostream & operator << (ostream &os, Character &ch);
};
ostream &operator << (ostream &os, Character &ch){
os << ch.c ;
return os;
}
istream &operator >> (istream &is, Character& ch){
is >> ch.c;
return is;
}
int main()
{
int cases, data;
Character ch;
int d;
cin>>cases;
for (int i = ; i < cases; i++)
{
cin>>ch;
cin>>data;
cout<<(ch + data)<<" "<<(ch - data)<<endl;
}
}

编译上边的代码,我们得到一连串编译错误信息,看的头都大。不过不要过于担心。我们经常会因为一个小错误产生连锁反应才产生了如此多的错误。我们要做的是查找最本源的那个bug。

首先我想到的可能<<的重载写的有问题,我查阅了iostream,ostream头文件的源码,确定了与之相关的函数

  inline basic_ostream<_CharT, _Traits>&  operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s);
2 inline basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c);

我根据源码判断,<<重载的大致应该是这个函数,从刚才的一大串编译错误中似乎也能验证这一点,里面包含源码中的第2行语句。

于是我根据源码第一行有const 这一事实,把<<的重载函数第二个参数前边都加上const,往第一条语句靠拢,程序成功编译了。或者我去掉引用,往第二条语句靠拢,程序同样编译成功了,更改代码如下。

ostream &operator<<(ostream &os,Character a);
ostream &operator<<(ostream &os,const Character &a);

我们至此可以把程序改正确了。但还有一个问题没有解决,为什么仅仅去掉const就发生了编译错误了?

这时结合我们一开始探讨的例子,这段代码和文章一开始的代码情况基本一致。即把一个返回非引用值的函数传给Character &。这下我们可以搞明白问题出现的原因了————函数的返回值作为隐式常量赋值给非 常引用致错。

在此留几个还没搞明白的问题,提示:引用,类型转换,以备以后研究。

由作业题引发对C++引用的一些思考的更多相关文章

  1. Sql Server之旅——终点站 nolock引发的三级事件的一些思考

    曾今有件事情让我记忆犹新,那年刚来携程不久,马上就被安排写一个接口,供企鹅公司调用他们员工的差旅信息,然后我就三下五除二的给写好 了,上线之后,大概过了一个月...DBA那边报告数据库出现大量锁超时, ...

  2. 为什么我没有拔出钥匙 ——开锁引发的程序bug解决方案的思考

    http://blog.csdn.net/wojiushiwo987/article/details/8851204为什么我没有拔出钥匙                             ——开 ...

  3. EF中用Newtonsoft.Json引发的循环引用问题

    描述: 1.双向关系表a->b b->aList 2.在查询a引用b以后 3.用Newtonsoft.Json 去tojsonstring 4.一个只有6条数据的json串 出现了一屏幕字 ...

  4. 由swap引发的关于按值传递和引用传递的思考与总结

    函数的参数传递定义:在调用一个函数时,将实参传递给形参. C++中函数的参数传递有按值传递.地址传递和引用传递3种方式.注意:地址也是一种值,按值传递和按地址传递都是单向的值传递方式,即形参都不会回传 ...

  5. foreach 引发的值类型与引用类型思考

    用都知道的一句话概括:“引用类型在堆上,栈上只保存引用:值类型即可存放于栈上也可存放于堆上,值类型变量直接存储值本身”. class Program { static void Main(string ...

  6. finalize()和四种引用的一点思考

    一次对ThreadLocal的学习引发的思考 ThreadLocal对Entry的引用是弱引用,于是联想到四种引用的生命周期. 强引用,不会进行垃圾回收 软引用,JVM内存不够,进行回收 弱引用,下次 ...

  7. 一道面试题引发的对javascript类型转换的思考

    最近群里有人发了下面这题:实现一个函数,运算结果可以满足如下预期结果: add(1)(2) // 3 add(1, 2, 3)(10) // 16 add(1)(2)(3)(4)(5) // 15 对 ...

  8. C# 由范式编程==运算符引发对string内存分配的思考

    今天在看C#编程指南时(类型参数的约束http://msdn.microsoft.com/zh-cn/library/d5x73970.aspx)看到一段描述: 在应用 where T : class ...

  9. 从orderby引发的SQL注入问题的思考

    背景: 某一天准备上线,合完master之后准备发布了,忽然公司的代码安全监测提示了可能在代码中存在sql注入的风险,遂即检查,发现sql注入问题 既然碰到了这个问题,那就了简单了解下sql注入 基础 ...

随机推荐

  1. Yii2中使用Soap WebSerivce

    Soap是一种轻量的.简单的.基于XML(标准通用标记语言下的一个子集)的协议 WebService顾名思义就是web服务,web服务主要有两种,一种是基于soap类型的服务,一种是基于rest类型的 ...

  2. wdcp v3 pureftpd 无法登录问题解决

    wdcp v3 新建站点和ftp账号 单位无法登录ftp 在端口中也确实可以看到有进行在登录状态 错误原因: 防火墙端口没有开启该端口范围  20000-30000 这时候发现 改端口为20078  ...

  3. centos7下使用n grok编译服务端和客户端穿透内网

    (发现博客园会屏蔽一些标题中的关键词,比如ngrok.内网穿透,原因不知,所以改了标题才能正常访问,) 有时候想在自己电脑.路由器或者树莓派上搭建一些web.vpn等服务让自己用,但是自己的电脑一般没 ...

  4. python之变量的命名规则

    变量的命名规则: 1.变量名由数字.字母和下划线组成名 2.变量名不能以数字开头 3.禁止使用python中的关键字 4.不能使用中文和拼音 5.变量名要区分大小写 6.变量名要有意义 7.推荐写法: ...

  5. Qt——模态、非模态

    模态: 只能操作对话框非模态:要使用 QDialog *_d = new QDialog();_d->setattribute(Qt::WA_DeleteOnClose);_d->show ...

  6. Java两个线程实现交替运行-以交替打印奇偶数为例

    本文旨在两个线程交替运行,不多哔哔直接看代码吧 public class Work2 { static final Object object = new Object(); public stati ...

  7. C++ 数组复制

    参考:https://blog.csdn.net/huangxiaohui123/article/details/81984175 补充: int tu[N][N],dis[N][N]; memcpy ...

  8. [原创]python高可用程序设计方法

    有时候程序上的bug会导致程序引发诸如段错误的情况而导致程序异常退出,这时用crond服务来检测,就会有一段时间程序处于不可用的情况,为了增强程序的可用性,我们可以让子进程处理业务,而让主进程检测子进 ...

  9. 宁波Uber优步司机奖励政策(8月10号-16号)

    本周奖励: 8月10日-8月16日: 滴滴快车单单2.5倍,注册地址:http://www.udache.com/如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://w ...

  10. VIO 初始化小结 - 10.17

    最近几个月忙于博士毕业,找工作一直没有继续更新博客,希望以这一篇开始,每个月能够继续有几篇总结博客. 首先review一下比较著名的vio系统 Tightly coupled EKF: mainly ...