一、对于单纯的常量,用const替换#define;用内联函数替换宏函数

如果想表示一个常量,请使用const而不是#define,因为#define在预编译期被简单的替换,没有类型检查。而const变量会被编译,编译期间会进行类型检查,更加安全可靠。除了类型检查之外,由于#define只是简单的将宏名替换,所以会导致生成的目标代码更大,而const就不会

二、operator[]与const

在博客https://blog.csdn.net/Master_Cui/article/details/109532520中,operator[]的实现分成了两个版本,但是为啥const版本的operator[]需要返回const对象的引用?此外文中的operator[]实现较短,如果实现代码较多,能否用一个调用另外一个?

第一个问题:为啥const版本的operator[]需要返回const对象的引用?

如果const版本的operator[]没有返回const对象的引用,当写下这样的代码时

int main(int argc, char const *argv[])
{mystring t1("1234");const mystring t4=t1;char *p=&t4[0];*p='a';cout<<t4<<endl;return 0;
}

可见输出了a234,const对象被修改了,因为如果不对const版本的operator[]的返回值加const,那么,将返回一个字符的引用,这样就可以通过指针来修改数据,从而间接修改原来的const对象

当const版本的operator[]的返回值加上const后,返回的是一个const char的引用,此时用char 指针指向const char数据,

发生了下面的转化

const char t=data[0];
const char &rt=t;
char *p = &rt;

当编译器编译到第三行时,发现char *要指向一个const char *,所以报错,防止间接修改原来的const mystring对象

所以,const版本的operator[]的返回值要返回const数据的引用,防止数据被间接修改

第二个问题:能否用一个operator[]调用另外一个operator[]?

https://blog.csdn.net/Master_Cui/article/details/106885048

目前两个版本的operator[]的实现如下

char & mystring::operator[](size_t n)
{cout<<"operator[](size_t n)"<<endl;return data_[n];
}const char & mystring::operator[](size_t n) const
{cout<<"operator[](size_t n) const"<<endl;return data_[n];
}

代码很短,但是如果代码较长,能否用其中一个调用另一个,防止重复代码?

因为const成员函数不会修改成员,所以,不能用const成员你函数调用非const成员函数,所以,必须是非const版本调动const版本的operator[]

所以,会写下如下代码

char & mystring::operator[](size_t n)
{cout<<"operator[](size_t n)"<<endl;return operator[](n);
}

然而实际上并没有调用const版本的operator[],而是无限递归

所以直接调用不行,就需要想办法间接调用到const版本的operator[],因为const对象可以调用operator[],所以就需要构造一个const mystring,然后用构造出来的const对象来调用operator[],此时返回的是一个const char&,需要使用const_cast去除底层const,所以可以写下如下代码

char & mystring::operator[](size_t n)
{cout<<"operator[](size_t n)"<<endl;const mystring t=*this;const char &rt=t.operator[](n);return const_cast<char&>(rt);
}int main(int argc, char const *argv[])
{mystring c1="1234";cout<<c1[1]<<endl;
}

然后并没有发现要找到的字符2,相反却出现了一个空格和一个析构函数的调用。这是因为构造的const对象是个局部对象,operator[]执行结束后,局部对象被释放,所以局部对象的引用也就无效了,所以没有打印出来字符2

修改代码如下,将局部对象变成引用绑定*this,这样函数退出后,*this不会被释放,所以引用也有效

char & mystring::operator[](size_t n)
{cout<<"operator[](size_t n)"<<endl;const mystring &t=*this;//变成引用const char &rt=t.operator[](n);return const_cast<char&>(rt);
}

将上述代码改为一行代码如下

char & mystring::operator[](size_t n)
{cout<<"operator[](size_t n)"<<endl;return const_cast<char&>(static_cast<const mystring &>(*this)[n]);
}

可见这回出现了字符2,并且使用非const版本的operator[]调用了const版本的operator[],只不过代码丑的一批

所以,如果const版本的operator[]实现并不复杂的话,非const版本的operator[]代码重复就重复吧,毕竟可读性好,否则再考虑这种丑的一批的转换式写法

参考

《Effective C++》

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

C++编程进阶1(对于单纯的常量,用const替换#define、operator[]与const)相关推荐

  1. 编程进阶,学会使用_I、_O、_IO,以及volatile const的意义

    _I._O._IO在ST库里面的定义是: #define __I volatile const /*!< defines 'read only' permissions */  #define ...

  2. 【Java编程进阶】常量变量及作用域

    推荐学习专栏:Java 编程进阶之路[从入门到精通] 文章目录 1. 常量 2. 变量 2.1 变量声明和初始化 2.2 变量的分类和作用域 1. 常量 常量的概念不难理解,它的值就是字面显示的值,其 ...

  3. 【编程之路】Python编程进阶

    Python编程进阶 不使用中间变量,交换两个变量a和b的值. a, b = b, a 需要注意,a, b = b, a 这种做法其实并不是元组解包,虽然很多人都这样认为.Python 字节码指令中有 ...

  4. Shell 编程进阶笔记

    这几篇博文主要记录博主的Linux 学习之路,用作以后回顾和参考.大家可以选择略过也可以作参考. (一)Linux 初步笔记 (二)Linux 进阶笔记(一) (三)Linux 进阶笔记(二) (四) ...

  5. MOOS-ivp 实验五 MOOS编程进阶(3)

    MOOS-ivp 实验五 MOOS编程进阶(3) 经过近日的学习与摸索,我来重新完善以下实验五的相关内容,上次做到三分之二的内容放弃了,主要原因还是因为C++功底不够深厚,需要更多的学习和积累.经过我 ...

  6. MOOS-ivp 实验五 MOOS编程进阶(2)

    MOOS-ivp 实验五 MOOS编程进阶(2) 今天继续我的实验,感觉每个实验都要被卡住,这种感觉真的好难受,但是如果把问题成功的解决掉,又会给人以非常大的成就感.今天写这篇博客,希望我可以相对顺利 ...

  7. 【Socket网络编程进阶与实战】------ Socket网络编程快速入门

    前言 本篇博客主要是分享,socket网络编程进阶与实践☞socket网络编程快速入门 一.聊一聊Socket 学习目标与收获

  8. Python开发系列课程(11) - 面向对象编程进阶

    面向对象编程进阶 在前面的章节我们已经了解了面向对象的入门知识,知道了如何定义类,如何创建对象以及如何给对象发消息.为了能够更好的使用面向对象编程思想进行程序开发,我们还需要对Python中的面向对象 ...

  9. 实验七 MapReduce编程进阶

    实验七 MapReduce编程进阶 答案在链接里https://blog.csdn.net/weixin_45818379/article/details/117790528

最新文章

  1. 浪潮信息:企业互联网化下的数据平台升级 | 云·创课程实录
  2. php中的__call调用
  3. IBM Watson物联网平台的两个MQTT工具
  4. puppet enc mysql_精通Puppet配置管理工具
  5. 小蚂蚁学习PHP性能优化(2)--PHP语言级性能优化
  6. IAP升级功能编写初期的一些困惑与疑问---完毕功能后的总结
  7. MapReduce过程详解
  8. android checkboxpreference属性,Android CheckBoxPreference Default Value
  9. 163邮箱邮件服务器域名,注册申请网易免费域名邮箱服务
  10. 《张志俊揭秘太极拳》读书摘编
  11. Android RGB颜色对照表
  12. 按键精灵通过抓抓工具来获取坐标位置
  13. 基于卫星测深的牙买加沿岸水深测量
  14. Android 9 Pie
  15. 带刺玫瑰特别美?OLED屏幕画面美但眼睛会累
  16. 无线蓝牙耳机哪个价位性价比最高?500以内最好的蓝牙耳机推荐
  17. 软件开发2:代码检视
  18. android定位附近店铺,高德地图怎么添加店铺位置_高德地图定位怎么设置添加自己家店铺位置_攻略...
  19. python计算均值方差模型_如何从Python中的FIGARCH模型中得到条件均值和标准差?...
  20. 关于弱电间和机房的综合布线

热门文章

  1. 字符转换指令tr,col,expand
  2. copy()与deepcopy()
  3. 程序员非常重要的24个软技能(开始我的博客之旅)
  4. GPUImage滤镜之锐化
  5. Java基础学习总结(26)——JNDI入门简介
  6. Java服务器热部署的实现原理
  7. 我眼里的Exchange 2010 之:1—DAG
  8. 基于SSH实现医院在线挂号系统
  9. 温泉关一役历史资料(电影:斯巴达300勇士)
  10. 持续集成-软件和库的统一