使用dev c++进行一波教科书代码的练习时出现了一点问题,于是来记录一波。

报错信息如下:

[Error] cannot bind non-const lvalue reference of type 'std::String&' to an rvalue of type 'std::String'

解决方案:检查一下是不是需要const引用

以下是问题记录,大家可以酌情浏览(因为我的废话太多)

一、问题描述

(一)原始问题

在练习字符串运算符重载,按照书上的原代码进行了一波敲:

(大家就关注一下运算符=和+的重载就可以了,运算符>的重载我并没有用到)

/*P225*/
#include <iostream>
#include <cstring>
using namespace std;namespace std
{class String   //定义字符串类 {protected:int Length;char *Sp;public:String() //定义缺省构造函数 {Sp = 0;Length = 0;}String (const String &);   //定义复制构造函数 String (const char *s)       //定义初始化构造函数 {Length = strlen(s);Sp = new char[Length+1];strcpy(Sp, s);}~String(){if(Sp)  delete[]Sp;}void Show(){cout<<Sp<<endl;}void operator=(String &);  //  定义字符串赋值成员函数friend String operator+(const String &, const String &);        //定义字符串拼接友元函数int operator>(const String &);  //定义字符串比较成员函数};String::String(const String &s){Length = s.Length;if(s.Sp){Sp = new char [Length+1];strcpy(Sp, s.Sp);}else  Sp = 0;}void String::operator=(String &s){if(Sp)  delete[]Sp;Length = s.Length;if(s.Sp){Sp = new char [Length+1];strcpy(Sp, s.Sp);}else  Sp = 0;}String operator+(const String &s1, const String &s2){String t;t.Length = s1.Length + s2.Length;t.Sp = new char[t.Length+1];strcpy(t.Sp, s1.Sp);strcat(t.Sp, s2.Sp); return t;}int String::operator>(const String &s){int ret;if(strcmp(Sp,s.Sp)>0)  ret = 1;else ret = 0;return ret;}
} int main()
{String s1("SW"), s2("HW"), s3("DS");String s4(s1), s5, s6, s7;s5 = s2;s6 = s4+s3;s7 = s5+s3;s6.Show();s7.Show();return 0;
}

然后报错了:

(二)、为什么在创建对象的同时进行赋值就没有问题?

我第一次学这个也不知道到底是+的问题还是=的问题,所以我在主函数这里进行了一波微小的改变:

由此看出:如果我先建立s6,s7的对象,再对s6, s7进行拼接操作,就会报错;而如果我在建立对象的同时进行赋值,显然就没有出错。

二、问题解决

我以为是+的问题,但我后来突然发现,字符串赋值成员函数operator=的参数不是const类型:

修改成operator=(const &)后进行一波尝试:

/*P225*/
#include <iostream>
#include <cstring>
using namespace std;namespace std
{class String   //定义字符串类 {protected:int Length;char *Sp; public:String()    //定义缺省构造函数 {Sp = 0;Length = 0;}String (const String &);   //定义复制构造函数 String (const char *s)       //定义初始化构造函数 {Length = strlen(s);Sp = new char[Length+1];strcpy(Sp, s);}~String(){if(Sp)  delete[]Sp;}void Show(){cout<<Sp<<endl;}void operator=(const String &);    //  定义字符串赋值成员函数friend String operator+(const String &, const String &);        //定义字符串拼接友元函数int operator>(const String &);  //定义字符串比较成员函数};String::String(const String &s){Length = s.Length;if(s.Sp){Sp = new char [Length+1];strcpy(Sp, s.Sp);}else  Sp = 0;}void String::operator=(const String &s){if(Sp)  delete[]Sp;Length = s.Length;if(s.Sp){Sp = new char [Length+1];strcpy(Sp, s.Sp);}else  Sp = 0;}String operator+(const String &s1, const String &s2){String t;t.Length = s1.Length + s2.Length;t.Sp = new char[t.Length+1];strcpy(t.Sp, s1.Sp);strcat(t.Sp, s2.Sp); return t;}int String::operator>(const String &s){int ret;if(strcmp(Sp,s.Sp)>0)  ret = 1;else ret = 0;return ret;}
} int main()
{String s1("SW"), s2("HW"), s3("DS");String s4(s1), s5, s6, s7;s5 = s2;s6 = s4+s3;s7 = s5+s3; s6.Show();s7.Show();return 0;
}

就没有问题了:

三、一些写给自己的补充

那么,让我们想想原理吧!

(一)、为什么必须要const引用?

我在csdn查到这篇文章:

C++之error: cannot bind non-const lvalue reference of type ‘myString&’ to an rvalue of type ‘myString_digitalkee的博客-CSDN博客

好吧,为了更好地理解,我至少要搞清楚以下这件事情:

我把临时变量和局部变量的概念搞混淆了。

天真的我还以为把临时变量改成全局变量是不是就有编译通过的可能,太菜了

菜狗就是这样的,基础不牢T.T

我是看到这几篇文章才意识到原来我的基础问题这么大:

C/C++中的临时变量_小琛笔记-CSDN博客_c 临时变量

非const引用参数传入不同类型编译不过的理解(拒绝将临时对象绑定为非const的引用的形参是有道理的) - dzqabc - 博客园

在C/C++中,真正意义上的临时变量是看不见的,就是说它们不会出现在你的代码中,参考一下这句话(来自《More Effective C++》):
True temporary objects in C++ are invisible — they don't appear in your source code. They arise whenever a non-heap object is created but not named.

至此其实我仍然不能理解……但总之我现在记住了:临时变量不能作为非const引用参数,所以那里要需要const引用。

(二)、为什么临时变量作为const引用参数时,创建对象同时进行赋值就没有报错?

问了老师,说是“初始化”与“赋值”的问题。

比如说数组可以初始化,但不可以定义后再整体赋值。如以下代码编译可通过:

#include <iostream>
using namespace std;
int main()
{int b[5] = {1, 2, 3, 4, 5};   int a[2]; //a[5] = {1, 2, 3, 4, 5};    //wronga[0] = 1;a[1] = 2;return 0;
} 

C++中对象初始化方式_yang20141109的专栏-CSDN博客_c++ 初始化

赋值和初始化是肯定不一样的。赋值是指擦除当前值,用新值替代,而初始化是指创建变量的同时赋予初始值。赋值不一定初始化,初始化一定有赋值。

在这篇文章里,作者提到:

    2.拷贝初始化:使用等号(=)初始化一个变量,实际上执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去,拷贝初始化通常使用拷贝构造函数来完成。拷贝初始化不仅在我们使用=定义变量时会发生,在下列情况也会发生(1)将一个对象作为实参传递给一个非引用类型的形参。(2)从一个返回类型为非引用类型的函数返回一个对象。

我认为【s6 = s4+s3;】应该属于拷贝初始化

但是再往深入我就看不懂了,我太弱了,c++还有很多东西等着我去学习

【报错】关于[Error] cannot bind non-const lvalue reference of type ‘std::String‘ to an rvalue……的一个解决方案相关推荐

  1. error: invalid initialization of reference of type ‘std::string’ from expression of type ‘const s

    error: invalid initialization of reference of type 'std::string&' from expression of type 'const ...

  2. java报错“Syntax error on tokens, delete these tokens”、“Return type for the method is missing”

    今天从wps里复制了java代码,出现了报错, Syntax error on tokens, delete these tokens;Return type for the method is mi ...

  3. mybatis查询报错:com.mysql.cj.exceptions.DataConversionException: Cannot determine value type from string

    mybatis查询报错: com.mysql.cj.exceptions.DataConversionException: Cannot determine value type from strin ...

  4. Python opencv 库cv.imread()读取图片为空None,cv.imshow()报错:error: (-215:Assertion failed) _src.empty() in ..

    报错原因: cv.imread()读取图片为空None,原因很大可能是路径有问题,要么是在路径下找不到图片,要么就是路径中包含有中文(特别要注意是不是路径含有中文):图片读取为空从而导致了在显示图片时 ...

  5. 【项目问题】PM2管理器运行报错: Error: bind EADDRINUSE null:8360(阿里云服务器)

    本人后端是使用thinkjs项目创建的,npm run compile 编译后上传到服务器,发现报错:Error: bind EADDRINUSE null:8360 第一步:查看运行日志,报错原因是 ...

  6. C++ STL编译报错:error: error passing 'const' as 'this' argument

    用C++ STL(标准模板库)编写仿函数的时候,编译报错: error: passing 'const FindNameOrAddress' as 'this' argument of 'bool F ...

  7. React报错:Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

    前言 在今晚用React的Hook写页面的时候,在写一个tab栏,然后要点击切换不同的tab,然后出现了一个报错: Error: Too many re-renders. React limits t ...

  8. windows10下编译dllib报错: ERROR: Failed building wheel for dlib

    一.报错信息 在安装dlib的时候,使用pip进行安装 pip install dlib 二.解决方式 1.检查自己是否已经安装了cmake 首先要检测自己本机是否已经安装了cmake,因为安装dli ...

  9. mongodb报错 An error occurred while loading navigation: topology was destroyed

    情况描述,关了电脑,第二天查询数据,报错An error occurred while loading navigation: topology was destroyed 我的数据库连接代码如下: ...

最新文章

  1. 【学习笔记】启动Nginx、查看nginx进程、查看nginx服务主进程的方式、Nginx服务可接受的信号、nginx帮助命令、Nginx平滑重启、Nginx服务器的升级
  2. 服务器点播直播系统,服务器点播直播系统
  3. 如何面试.NET/ASP.NET工程师?
  4. linux ubuntu mysql 安装_1.MySQL的安装(linux Ubuntu环境下)
  5. 有关编辑距离计算的一点整理。
  6. 东营网站服务器部署,联通东营服务器dns地址
  7. virtualBox经常报错“内存不能为written”解决方法
  8. 宾夕法尼亚州立大学:探索量子AI如何加速治愈癌症
  9. ps4正在连接ea服务器,ps4极品飞车19连不上ea服务器 | 手游网游页游攻略大全
  10. 关于Vuex的基本使用
  11. 学python就业好吗_Python就业行情怎么样?Python好学吗?
  12. Ebean报错java.lang.ClassCastException: com.project.model.xxx cannot be cast to com.project.model.xxx
  13. ubuntu中如何修改计算机名字
  14. TMS320F28374芯片简介
  15. 从首个IMO季军谈起 作者 : 付云皓
  16. LinuxC——指针
  17. input的各种事件
  18. java split 冒号_Java中字符串split() 的使用方法,没你想的那么简单
  19. 浅谈《数学之美》①——自然语言处理
  20. linux打补丁要选择目录,Linux下patch打补丁命令实例详解

热门文章

  1. 在cocos2dx中实现水波滤镜
  2. Vue前端神策数据埋点
  3. c语言显示德国国旗代码_德国项目启动代码
  4. 将所有的空格换成逗号
  5. Python统计文件行数
  6. 【转】Android APP性能及专项测试(个人整理)
  7. 大学生计算机论文评语简短,大学生毕业论文评语
  8. springboot dubbo负载均衡配置
  9. 除去pdf文件内部的超链接/a标签
  10. 数据库系列(2):数据库系统的发展