声明C++变量为const是否有助于提高性能?

9

我理解const限定的数据类型的行为。然而,我很好奇,过度或不够热情地将变量标记为const是否会带来性能上的收益或损失。特别是对于仅在隔离的代码块中声明和使用的变量。例如:

const qreal padding = CalculatePadding();
const QSizeF page_size = CalculatePagePreviewSize(padding);
const QRectF content_rect = CalculatePagePreviewContentRect(page_size);
const QList<QRectF> pages = renderer.BuildPrintPages(printer_, map_scene_);
const QFont page_number_font = CalculatePageNumberFont();
const QFontMetrics metrics(page_number_font);

假设我只需要在所有这些方法上使用const修饰符(以及更多)。将它们全部声明为const是否有任何性能优势?或者相反,这实际上会损害性能吗?
我对运行时性能和编译时性能都很好奇(我猜这不会有什么区别,因为const是一个专门的编译时检查 - 有人可以确认吗?)。我没有足够的c++经验来感受到这一点,并且想知道当所有其他事情(可维护性等)相等时,我是否应该过度或不够应用const

2
在大多数情况下,没有运行时性能差异。 - Anycorn
2
重复的问题?https://dev59.com/tnA75IYBdhLWcg3wK1wp - Anycorn
Qt很多地方采用了写时复制技术,因此我认为const关键字在这里可能会产生真正的影响。 - Johannes Schaub - litb
6个回答

27

const主要是编译时的一个东西,然而,将某些内容声明为const有时允许进行特定的优化。 如果相关代码不是性能瓶颈,我就不会担心它,只需按照意图使用const:生成更清晰的代码并防止自己做愚蠢的事情。


4

根据我的有限经验,const修饰符可能会严重影响性能(惊讶!) 具体地说,在使用容器类时要注意其是否被标记为const:对于数组而言,一旦仅读取一个元素,编译器可能会强制复制容器(例如,数组)… 这是我正在处理的代码中很大的痛点。


2

我的理解是const可以被编译器用于潜在的性能优化,但不能保证;然而,这不应该有性能下降。它可能会影响运行时行为(例如:编译器可以将const变量放置在只读内存页中)。

它不应该对性能产生重大影响,但我更倾向于使用它来方便代码维护。当然,这只是我的意见。


2
是的,如果应用于对象本身,const可以提高性能。 示例
int fmutable(void g(const int &)) {
    int x = 1;
    g(x);
    return x;  // mov rax, dword ptr [rsp + ...]
}

int fconst(void g(const int &)) {
    int const x = 1;
    g(x);
    return x;  // mov eax, 1
}

这是因为对一个 const 对象进行改变是非法的,所以编译器可以假设你不会这样做。
然而,将 引用指针 的目标添加 const 并不能提高性能,因为去除 const 并且对原本不是 const 的对象进行改变是合法的,编译器无法假设你不会这样做。

1
虽然在技术上答案是“是”,但实际上的答案是“否”。编译器确实可以在特定情况下通过考虑给定值不会改变或方法不会修改所拥有的对象来执行代码优化。然而,这些都是具有情境性的情况,而且在优化的细节中如此深入到几乎肯定事先考虑这一点是错误的。

0

const 只是为了帮助您在编译时捕获错误。但是,由于有这个叫做 const_cast 的东西,您始终可以更改任何变量的常数性,因此编译器无法摆脱任何优化。 (您还可以使用 C 风格的转换来消除常数性,这可能会使优化无效。)


1
始终避免使用const_cast,只有在没有选择的情况下才使用它(例如:您正在使用无法更改接口的外部库,但知道修改常量对象是“足够安全”的)。 - rubenvb
2
这并不完全正确。如果您将变量定义为const,则无法将其强制转换并写入其中。编译器根据变量为const缓存变量值是可以的。任何写入const变量的程序都具有未定义的行为。 - Johannes Schaub - litb
约翰内斯 - const 和优化的谷歌搜索中的第一个结果:http://www.gotw.ca/gotw/081.htm - 你可以尝试自己写入一个非const变量。 - miked
2
你所提到的链接是一个不同的情况,其中你会得到一个指向可能不是常量对象的常量引用。 Johannes所指的是变量最初声明为 const type name 的情况,在那里修改 name 是未定义行为。例如,符合规范的编译器可以决定将该变量放置在 ROM 中而不是普通内存中,或者放在只读内存页中。在这两种情况下,尝试修改变量可能会无声失败或导致应用程序崩溃。 - David Rodríguez - dribeas
2
如果您通过将非const对象绑定到常量引用来添加const属性,则可以取消const属性并进行修改,这是可以的。但是您不能取消已经是const的对象的const属性。 - David Rodríguez - dribeas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接