前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Effective C++条款3 我可以不使用const?

Effective C++条款3 我可以不使用const?

作者头像
ACM算法日常
发布2020-10-10 11:33:42
5550
发布2020-10-10 11:33:42
举报
文章被收录于专栏:ACM算法日常ACM算法日常

前言

const是C++中用得非常频繁的一个关键字,但是如果你不使用这个关键字,对程序的运行结果影响不大,那么,我可以不使用const吗?

一开始,拒绝使用const的最大原因一般是觉得这个关键字比较鸡肋,因为它不会对程序产生实质影响,而且很繁琐,变量加上const关键后只能调用const类型的函数,极不方便。

但是为了安全,推荐使用const,这是一个良好的习惯,坚持下去的结果是你的代码将变得更加健壮,当然你也可以不使用const,只不过当代码量到一定程度后,你的代码将会变得比较脆弱,而且随着量级的一步步升高,存在的隐患也会一点点增加。

大部分难缠的问题都和内存有关系,如果再加上多线程,将会是一场噩梦。C/C++中存在很多未定义的行为,一个拥有几十个线程的程序,其中一个线程的内存写入或者释放出了问题,可能会造成随机的任意一个线程发生崩溃,如果每次崩溃的位置都随机,难度可想而知(你会怀疑整个程序到处都是bug,但其实只是一处微小的bug引起)。

const是解决这些问题的一个小部件,它提供了一种约束,让问题能够提前暴露出来,也要求程序员能够严格的去对成员函数进行区分,另外对于别人使用来说,能够一目了然的知道哪些函数是安全的,哪些函数会修改变量。

const定义变量

const定义变量,表示这个变量不可修改,如下:

代码语言:javascript
复制
// 常量字符串
const char * s = "hello world";

需要注意的是,const出现在*的左边,表示变量指向的值不会改变,可以通过上面这种常用的例子来记忆,hello world是字符串常量,自然是不会改变的。如果const在*的右边,表示该指针是常量。

const定义函数

const修饰类成员函数,表示这个函数只能被const的对象调用。

const函数不会修改任何成员变量,除非这个变量是mutable类型的,也就是说,mutable类型的变量可以在const函数中进行赋值操作。

const函数的优点:

  • 能够提高程序的可读性,哪些函数可写,哪些函数只读一目了然;
  • const对象可以调用

对于const函数,如下代码,const对象a会调用const的print,b则调用普通的print,一般来说,non-const版本可以调用const版本的实现,避免重复。

代码语言:javascript
复制
class Printer{
public:
  void print() const;
  void print();
};

int main()
{
  Printer a;
  const Printer b;
  a.print();
  b.print();
  return 0;
}

const引用传递

条款18中,主要针对函数参数使用引用还是直接传值的问题,一般来说,函数参数如果是类,都应该采用引用或者指针的方式来提高效率,避免不必要的开销。

传值需要调用构造函数和析构函数,优点是不会修改数据。

采用const引用,既可以避免多余的函数调用,也能保证数据不被修改。

如果不使用const直接传递引用,调用者会认为这个对象是可以被更改的。

const与线程安全

现在,让我们来思考一下const对象是线程安全的吗?

某种程度上来说,const对象是线程安全的,因为const承诺不会修改任何数据。

但是如果你使用了mutable关键字,那么情况就不一样了,因为这个关键字使得你可以在const函数中修改mutable类型的值。

线程安全在C++中的语言标准是这样的:

[1.10/4] Two expression evaluations conflict if one of them modifies a memory location (1.7) and the other one accesses or modifies the same memory location.

[1.10/21] The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other. Any such data race results in undefined behavior.

简单说就是对于一块内存地址,当存在多个actions时,只要有一个写入就会发生数据竞争,也就会出现线程安全问题。

一般来说,我们需要保证const函数是线程安全的,在《Effective Modern C++》第16项条款中,Scott Meyers强调了这一点,当一个函数被声明为const时,就应该保证这个函数是线程安全的。随着技术的发展,单线程的场景会越来越少见,也因此这一条款会变得更加重要。

总结

const是一种约束,能让变量更加安全,能让接口变得更加清晰,对于const成员函数,还应该保证它的实现是线程安全的,另外,使用const引用能够避免传值的低效率,也能保证数据不被修改。

const是一个良好的习惯,如果你正在编写一个有一定代码量的项目,那么const一定是一个不错的选择。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ACM算法日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • const定义变量
  • const定义函数
  • const引用传递
  • const与线程安全
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档