我已经阅读了关于C++中const-correctness的所有建议,并且它(部分)很重要,因为它有助于编译器优化代码.我从未见过的是关于编译器如何使用这些信息来优化代码的一个很好的解释,甚至连好书都没有解释幕后发生的事情.
例如,编译器如何优化声明为const的方法与不应该但应该是的方法.当你引入可变变量时会发生什么?它们会影响const方法的这些优化吗?
我认为const关键字主要用于编译检查程序语义,而不是用于优化.
Herw Sutter在GotW#81文章中解释了为什么编译器在通过const引用传递参数时或者在声明const返回值时无法优化任何内容.原因是编译器无法确定引用的对象是否会被更改,即使声明为const:one可以使用const_cast,或者某些其他代码可以在同一对象上具有非const引用.
然而,引用Herb Sutter的文章:
只有一种情况说"const"可以真正意味着某种东西,那就是当对象在它们被定义的点被制成const时.在这种情况下,编译器通常可以成功地将这种"真正的const"对象放入只读存储器中[...].
本文还有很多内容,所以我鼓励您阅读它:在此之后您将更好地理解持续优化.
让我们忽略方法,只看const对象; 编译器在这里有更多的优化机会.如果一个对象被声明为const,那么(ISO/IEC 14882:2003 7.1.5.1(4)):
除了可以修改声明为mutable(7.1.1)的任何类成员之外,任何在其生命周期内修改const对象的尝试(3.8)都会导致未定义的行为.
让我们忽略可能具有可变成员的对象 - 编译器可以自由地假设该对象不会被修改,因此它可以产生重要的优化.这些优化可以包括以下内容:
将对象的值直接合并到机器指令操作码中
完全消除永远无法访问的代码,因为const对象用于编译时已知的条件表达式
如果const对象控制循环的迭代次数,则循环展开
请注意,只有当实际对象是const时,这个东西才适用 - 它不适用于通过const指针或引用访问的对象,因为这些访问路径可能导致非const的对象(它甚至可以很好地定义为通过const更改对象)指针/引用,只要实际对象是非const并且您丢弃了对象的访问路径的常量).
在实践中,我认为没有编译器可以对各种const对象执行任何重要的优化.但对于原始类型的对象(整数,字符等),我认为编译器可以非常积极地优化这些项的使用.
handwaving开始
本质上,数据修复得越早,编译器就可以越多地绕数据的实际分配移动,确保管道不会停顿
结束了
咩.正确性更像是一种样式/错误检查,而不是优化.完全优化的编译器将遵循变量使用,并且可以检测变量何时是否有效.
除此之外,编译器不能依赖于你说实话 - 你可能会丢弃它不知道的库函数中的const.
所以,是的,const-correctness是一个值得瞄准的东西,但它并没有告诉编译器任何它不会为自己弄清楚,假设一个好的优化编译器.