"const"声明有助于编译器(GCC)生成更快的代码吗?

Max*_*axB 7 c c++ performance gcc g++

const声明是否有助于编译器(GCC)生成更快的代码,或者它们仅对可读性和正确性有用吗?

Zed Shaw认为const在C/C++中无用或过度使用:

接下来是const的所有奇怪的魅力.由于一些奇怪的原因,C++喜欢让你在声明的每个部分都使用const,但是我得到与C相同的最终结果:调用一个函数.(......)

(来自:http://librelist.com/browser//mongrel2/2010/7/15/c-verses-c++/#770d94bcfc6ddf1d8510199996b607dd)

Kon*_*lph 11

是.这是一个具体的例子.const可以通过const&而不是通过值传递参数(这可能需要昂贵的副本).重要的是要意识到传递的替代const&方法不是通过 - &因为后者不允许临时绑定.所以,例如,这段代码:

auto result = foo{1} + foo{2} + foo{3};
Run Code Online (Sandbox Code Playgroud)

可以打电话foo operator +(foo const&, foo const&)但可能打电话foo operator +(foo&, foo&).

这样,const有助于避免复制.

但一般来说,这const是一种确保正确性的工具,而不是帮助优化.

无论哪种方式,Zed Shaw都不知道他在说什么.顺便说一下,他的其余咆哮同样被误导了.


zne*_*eak 5

不,const不会帮助编译器编写更快的代码。Const是用于const正确性,而不是优化。

C ++标准说const不能修改项目,但const_cast应从const对象中删除修改器并使它可写(除非它位于实际的只读存储器中,在这种情况下行为是未定义的)。因此const,通常这并不意味着目标变量不会更改。

我只能想到这两个非常狭窄的场景,它们const产生的代码比没有它产生的代码快:

  • 该变量是具有内部链接(static)的全局变量,并通过引用或指针传递给在不同转换单元(不同文件)中定义的函数。在这种情况下,如果未标记,编译器将无法取消对其的读取const
  • 该变量是具有外部链接(extern)的全局变量。const extern可以在定义它的文件内忽略对a的读取(但无其他地方)。

const应用于全局变量时,允许编译器假定该值永远不会改变,因为它将把它放置在只读内存中,这意味着如果程序尝试对其进行修改,则表示未定义的行为,并且编译器作者喜欢依赖对不确定行为的威胁,以使代码更快。

请注意,这两种情况适用于全局变量,这可能只占程序中很小一部分的变量。然而,就其优点而言,它const意味着static在C ++中是全局级别的(在C中不是这种情况)。

上面有人说,使用const可以使代码更快,因为可以使用const引用。我在这里争论说,使代码更快的原因是引用的使用,而不是的使用const

就是说,我仍然相信这const是一把非常锋利的刀,您无法用它割伤自己,我建议您在适当的时候使用它,但出于性能方面的考虑,不要使用它。


Jar*_*Par 3

一般来说,const由于多种原因,方法、引用和指针的修饰符不能用于优化代码。第一个是const,在这些情况下,修饰符不能保证底层数据不会改变,它只是让修改它变得更加困难。这是一个经典的例子

void M(const C& p1, C& p2) { 
  cout << p1.field << endl;
  p2.Mutate();
  cout << p1.field<< endl;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,很可能p1.field在此代码中进行了修改。最明显的情况是p1p2引用相同的值。

C local;
M(local, local);
Run Code Online (Sandbox Code Playgroud)

因此编译器在这里无法进行真正的优化。该const参数与非常量参数同样危险。

它无法真正优化的另一个原因是任何人都可以在 C++ 中使用const_cast.

class C { 
public:
  int field;

  int GetField() const { 
    C* pEvil = const_cast<C*>(this);
    pEvil->field++;
    return field;
  }
};
Run Code Online (Sandbox Code Playgroud)

因此,即使您正在处理单个const引用,这些值仍然可以在幕后自由更改。