[翻译] const 是否会对程序的优化产生影响

wzzzx:来源:http://www.gotw.ca/gotw/081.htm

1. 函数参数声明为const和返回值声明为const,是否会对编译器优化代码产生影响?

  // Example 1
  //
  const Y& f( const X& x )
  {
    // ... do something with x and find a Y object ...
    return someY;
  }

简要地说,也许并不会。
编译器能做的更好的是什么?它能够避免传参和返回值的拷贝开销吗?并不,因为参数和返回值是通过引用来进行传递的。它能够将xsomeY拷贝到只读内存区域吗?也不会。对于xsomeY而言,它们的生命周期均在该函数的作用域之外。即便someY是在函数内部动态创建的,它的所有权也会被传递给调用者。
但在f()的内部,有没有可能会对代码进行一定的优化呢?因为const的存在,会不会在某种程度上导致编译器生成更加优化的代码呢?

2. 从一般化的情况来看,使用与否const为什么会对编译器的代码优化产生影响

回到Example 1,使用const修饰参数不会导致编译器对代码产生额外优化的原因是,即便调用一个const类成员函数,编译器也没法认定xsomeY的值不会发生改变。再者,除非编译器进行全局优化,不然会有其他的一些问题存在:首先,编译器并不知道其他的代码会不会持有对象xsomeY的非const引用,这些变量可能会在f()执行期间被意外地使用。其次,编译器也不一定会知道,xxomeY所引用的对象,是否是被主动声明为一个const变量。
仅仅因为xy被声明为const常量,也不一定意味它们物理上的位是常量。因为这些类可能会存在可变成员,或者其他等价的东西,即在成员函数内部进行const_cast强制转换或者C语言样式的强制转换,导致被声明为const常量并不是一个真正的常量。
只有在变量定义的时候,声明为const常量,此时说const常量才具有意义。特别是这些变量是能够在编译期间就生成的POD类型时,编译器可以将这些真正的const常量对象放置到只读内存中,同时会被存储到可执行文件本身。这样的对象会被称为ROM-able

3. 依下列代码考虑三个小问题:

  // Example 3
  //
  void f( const Z z )
  {
    // ...
  }

有三个小问题需要思考:

  1. 什么环境下,某些特定类型的Z是否可以使编译器生成不一样且更好的代码?
  2. 在问题 a 所提及的情况下, 我们是在讨论编译器的优化还是其他方面的优化。
  3. 有更好的取得相同的效果吗?

3.1 什么环境下,某些特定类型的Z是否可以使编译器生成不一样且更好的代码?

简要回答就是:能,也不能。
先说一下能的部分。因为编译器知道z是一个真正的常量对象,所以可以在没有进行全局优化的情况下,进行一些有用的优化。例如,如果在f()内有一个这样的调用:g(&z)。编译器可以明确地知道在调用g()的时候,z不会发生变化。
除此之外,在参数值声明为const常量,对于大多数的z而言,并不会产生任何形式的优化。在这种情况下的优化,并不是编译器代码生成优化。
对于编译器代码生成优化,问题主要归结为编译器是否可以省略拷贝构造,或者是否可以将z放入只读内存中。这意味着,对象zf()函数内部不会受到任何的影响,所以我们可以直接使用函数外部的对象而不需要多一次的拷贝赋值操作。或者即便需要拷贝,也可以直接将拷贝后的对象直接放置在只读内存中,用到的时候直接读取。
一般情况下,编译器不会因为参数是const的就主动消除拷贝构造函数。如同上文所提到的一样,这可能会导致太多的问题。尤其是Z拥有可变成员的时候,或者在其他地方直接或间接使用到Z的成员函数时,可能会使用const_casts来改变常量。
但有一些办法来帮助编译器生成更好的代码,如下几点:

  • 对于Z的拷贝构造函数和所有在f()中直接或间接用到的成员函数都是可见的。
  • 这些函数都非常简单且没有任何副作用
  • 编译器有较为激进的优化策略

满足上述三点会让编译器明确每一步具体发生了什么,所以编译器能够在as-if规则的限制下,自主选择消除一些不必要的代码。
另外,还有一点值得一提。有些人会说编译器执行全局优化的时候,可以对const常量提供优化以生成更好的代码。事实上,即便去掉const修饰,也可以对生成代码进行优化。不要介意全局优化的频次低且代价高。这里真正的问题是全局优化清楚所有对象的真正使用情况,所以不管有无声明为const,都会执行相同的优化操作。全局优化针对的是你真正的操作,而不是你承诺会做的操作。因此如果你执行了真正的全局优化,const的声明并不会对优化器产生任何的影响。
注意上文所说的,Example 3中的大多数Z声明为const对编译器生成代码并不会有任何的优化。然而,编译器的优化器还是可能存在一些优化的。实际上,const也可以有一些真正的优化的。

在问题 3.1 所提及的情况下, 我们是在讨论编译器的优化还是其他方面的优化。

实际上存在程序性的优化,Z可以智能的选择不同的方式来针对const对象。作为例子,我们可以认为Z是一个handle类,例如String会使用引用计数来完成懒复制。

  // Example 4
  //
  void f( const String s )
  {
    // ...
    s[4]; // or use iterators
    // ...
  }

类似于String,对有const修饰的String执行operator[]()时,不可以修改字符串的内容,这也许可以提供一个重载函数,该函数返回值而非引用。

  class String
  {
    // ...
  public:
    char  operator[]( size_t ) const;
    char& operator[]( size_t );
    // ...
  }

类似于,String也可以提供const_iterators,调用operator*()会返回值而非引用。
如果你使用operator[]()iterators,并且传参时使用const修饰,你会发现,String会自动地帮助你避免深拷贝。

3.3 有更好的取得相同的效果吗?

你可以通过简单的方法来获得上述效果。

  // Example 5: Just do it -- better than Example 3
  //
  void f( const Z& z )
  {
    // ...
  }

现在不管对象是不是一个handle类或引用计数的东西,都可以实现避免深度拷贝的优化。这也是一个准则,使用const引用的方式来传递参数,而不是简单的const值传递。
这样可以帮助编译器生成更紧凑的代码。const是一个好东西,但是更多的是对人类而言。当希望写出安全的代码的时候,const可以强制编译器进行检测。在优化阶段,const也是一个有用的工具,用于帮助类设计者实现手动优化,但是对编译器优化生成代码这方面却没有那么大的帮助。

wzzzx:之所以翻译这个是因为前阵子跟朋友讨论到 const 对于代码优化的影响,然后查看到了这个博客。所以今儿抽空做了一个翻译,有不好理解的地方欢迎指出~

codehz:原作者没有考虑 alias 分析的问题,虽然为了照顾程序员很多编译器是很保守的,但是有些编译器可以对 const 引用做更为激进的优化

https://software.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-reference/top/compiler-reference/compiler-options/compiler-option-details/advanced-optimization-options/alias-const-qalias-const.html?language=en

一键拷贝常用动画效果 CSS 代码

jeffjade:CSSFX,一个 CSS 动效相关的网站: https://cssfx.lovejade.cn/ 。她集合 Web 开发中常用的动画效果,如鼠标悬停、输入框获取焦点、加载、以及其他动画;不仅有展示效果,并提供一键拷贝至剪切板,以便您可以在自己的项目中使用。 备注:这个项目是基于 GitHub 的一个项目( CSSFX ?) fork 而来,…

在PHP中将Integer转换为十六进制值 - php

如何将PHP第一类中的数字转换为第二类中的数字,是否有内置函数转换数字?这也是我的头衔将整数转换为十六进制值”是否正确?class Permission { const READ = 1; const UPDATE = 2; const DELETE = 4; const COMMENT = 8; const GRANT = 16; const UNDELE…

敲代码时,不知不觉背部就紧张了起来

magicianjaychou:敲代码时,不知不觉背部就紧张了起来意识到以后主动放松下来,会感到很累这段时间经常这样,大家有过类似的经历吗?

计算机专业本科大四,找不到计算类实习,面临无法毕业,怎么办才好?

webpy:普通一本本科计算机专业,学校要求必须有计算机研发相关的实习才能拿到实习学分毕业,但我编程类的完全不懂也不感兴趣,只能找到非技术类的工作。那就意味着达不到毕业条件,很可能无法毕业。有朋友遇到过类似情况吗?很迷茫,求打醒补充:这个贴子是帮我表弟发的,他自己编辑的,所以看起来是第一人称。我本人已工作几年,但我自己不是计算机专业毕业的,所以也给不了建议,…

上海有哪些地方适合周末抱着电脑去写代码,大佬们周末休息时间一般去哪写代码呢

zhanbiqiyu:想周末出去写代码,自己一个人在家宅着感觉要废了,想周末找个地方可以看看书写代码,上海的大佬们一般去哪里呢,有不错的地方可以推荐下,谢谢大佬wushigejiajia01:周末了 就歇会儿吧