专栏首页ACM算法日常Effective C++条款3 我可以不使用const?

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

前言

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

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

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

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

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

const定义变量

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

// 常量字符串
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版本的实现,避免重复。

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一定是一个不错的选择。

本文分享自微信公众号 - ACM算法日常(acm-clan),作者:dansen

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 我如何克服对编程的恐惧

    我在2015年写了我的第一个C程序。我仍然记得当我完成时的狂喜,即使我只是完成了最简单的程序。

    ACM算法日常
  • leetcode 14 | 最长公共前缀

    分析:找到数组中长度最小的元素min(从后面更快的例子来看,这个好像不需要~),然后从min的第一字符开始,去查找剩余元素是否在相同位置是同一个字符。

    ACM算法日常
  • 洛谷1638(尺取)

    可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字,a和b,代表他要看展览中的第 a 幅至第 b 幅画(包含 a 和 b)之间的所有图画,而...

    ACM算法日常
  • const关键字应用总结

    C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,通过查阅资料,将const作用归纳如下:

    公众号C语言与CPP编程
  • QMap容器小知识

    Qt君
  • 学习c++中的小问题总结

    徐飞机
  • C++雾中风景3:const用法的小结

    const关键字,翻译成中文是常量,常数的意思。所以在绝大多数场合之中,const是来定义常量的,定义常量也是好的编程习惯。在C类语言之中,定义常量通常会使用宏...

    HappenLee
  • 初级程序员面试不靠谱指南(二)

    3.read-only的const。如果你突然冒出一句看似很高深的话但又不解释一般都是装逼,就像前面提到过const准确的应该理解为一个read-only的变量...

    一心一怿
  • const特性总结(不断更新)

    作者:bakari  时间:2012.6.5 1、指向const对象的指针---const int *cptr; i、在此,cptr是指向int类型的const...

    CloudDeveloper
  • 我在大厂写React,学到了什么?

    我工作中的技术栈主要是 React + TypeScript,这篇文章我想总结一下如何在项目中运用 React 的一些技巧解决一些实际问题,本文中使用的代码都是...

    ssh1995

扫码关注云+社区

领取腾讯云代金券