問題描述
我知道它提高了可讀性并使程序不易出錯,但它對性能的提高有多大?
I know that it improves readability and makes the program less error-prone, but how much does it improve the performance?
順便提一下,引用和 const
指針之間的主要區別是什么?我會假設它們以不同的方式存儲在內存中,但如何?
And on a side note, what's the major difference between a reference and a const
pointer? I would assume they're stored in the memory differently, but how so?
推薦答案
聲明常量指針或常量引用永遠不會幫助任何編譯器優化任何東西.(盡管請參閱此答案底部的更新.)
Declaring a pointer-to-const or reference-of-const never helps any compiler to optimize anything. (Although see the Update at the bottom of this answer.)
const
聲明僅指示如何在其聲明的范圍內使用標識符;并不是說底層對象不能改變.
The const
declaration only indicates how an identifier will be used within the scope of its declaration; it does not say that the underlying object can not change.
示例:
int foo(const int *p) {
int x = *p;
bar(x);
x = *p;
return x;
}
編譯器不能假設 *p
沒有被 bar()
的調用修改,因為 p
可能是(例如)指向全局 int 的指針,bar()
可能會修改它.
The compiler cannot assume that *p
is not modified by the call to bar()
, because p
could be (e.g.) a pointer to a global int and bar()
might modify it.
如果編譯器足夠了解foo()
的調用者和bar()
的內容,它可以證明bar()
不修改*p
,那么它也可以在沒有 const 聲明的情況下執行該證明.
If the compiler knows enough about the caller of foo()
and the contents of bar()
that it can prove bar()
does not modify *p
, then it can also perform that proof without the const declaration.
但總的來說,這是真的.因為const
只在聲明的范圍內起作用,編譯器已經可以看到你在該范圍內如何處理指針或引用;它已經知道您沒有修改底層對象.
But this is true in general. Because const
only has an effect within the scope of the declaration, the compiler can already see how you are treating the pointer or reference within that scope; it already knows that you are not modifying the underlying object.
所以簡而言之,所有 const
在這個上下文中所做的就是防止你犯錯誤.它不會告訴編譯器任何它不知道的東西,因此它與優化無關.
So in short, all const
does in this context is prevent you from making mistakes. It does not tell the compiler anything it does not already know, and therefore it is irrelevant for optimization.
那些調用 foo()
的函數呢?喜歡:
What about functions that call foo()
? Like:
int x = 37;
foo(&x);
printf("%d
", x);
由于foo()
接受一個const int *
,所以編譯器能證明這會打印37嗎?
Can the compiler prove that this prints 37, since foo()
takes a const int *
?
沒有.即使 foo()
接受一個指向常量的指針,它也可能會拋棄常量并修改 int.(這是不是未定義的行為.)這里再次重申,編譯器一般不能做出任何假設;如果它對 foo()
有足夠的了解來進行這樣的優化,它就會知道即使沒有 const
.
No. Even though foo()
takes a pointer-to-const, it might cast the const-ness away and modify the int. (This is not undefined behavior.) Here again, the compiler cannot make any assumptions in general; and if it knows enough about foo()
to make such an optimization, it will know that even without the const
.
const
可能允許優化的唯一時間是這樣的情況:
The only time const
might allow optimizations is cases like this:
const int x = 37;
foo(&x);
printf("%d
", x);
在這里,通過任何機制(例如,通過獲取指向它的指針并丟棄 const
)來修改 x
就是調用未定義行為.因此編譯器可以自由地假設您不這樣做,并且它可以將常量 37 傳播到 printf() 中.這種優化對于您聲明 const
的任何對象都是合法的.(實際上,您從不引用的局部變量不會受益,因為編譯器已經可以看到您是否在其范圍內修改了它.)
Here, to modify x
through any mechanism whatsoever (e.g., by taking a pointer to it and casting away the const
) is to invoke Undefined Behavior. So the compiler is free to assume you do not do that, and it can propagate the constant 37 into the printf(). This sort of optimization is legal for any object you declare const
. (In practice, a local variable to which you never take a reference will not benefit, because the compiler can already see whether you modify it within its scope.)
要回答您的旁注"問題,(a) const 指針是一個指針;(b) const 指針可以等于 NULL.您是正確的,內部表示(即地址)很可能是相同的.
To answer your "side note" question, (a) a const pointer is a pointer; and (b) a const pointer can equal NULL. You are correct that the internal representation (i.e. an address) is most likely the same.
[更新]
正如 Christoph 在評論中指出的那樣,我的回答是不完整的,因為它沒有提到 restrict代碼>.
As Christoph points out in the comments, my answer is incomplete because it does not mention restrict
.
C99 標準的第 6.7.3.1 (4) 節說:
Section 6.7.3.1 (4) of the C99 standard says:
在每次執行 B 期間,讓 L 是任何基于 P 具有 &L 的左值.如果 L 用于訪問它指定的對象 X 的值,并且 X 也被修改(以任何方式),那么以下要求適用: T 不應是 const 限定的....
During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified. ...
(這里 B 是一個基本塊,P,一個指向 T 的限制指針,在其作用域內.)
(Here B is a basic block over which P, a restrict-pointer-to-T, is in scope.)
因此,如果 C 函數 foo()
被聲明如下:
So if a C function foo()
is declared like this:
foo(const int * restrict p)
...那么編譯器可能假設在p
的生??命周期內不會對*p
進行修改——即,在foo()
的執行——否則行為將是未定義的.
...then the compiler may assume that no modifications to *p
occur during the lifetime of p
-- i.e., during the execution of foo()
-- because otherwise the Behavior would be Undefined.
因此,原則上,將 restrict
與指向常量的指針相結合可以實現上面忽略的兩種優化.我想知道有沒有編譯器真的實現了這樣的優化?(至少 GCC 4.5.2 沒有.)
So in principle, combining restrict
with a pointer-to-const could enable both of the optimizations that are dismissed above. Do any compilers actually implement such an optimization, I wonder? (GCC 4.5.2, at least, does not.)
請注意,restrict
僅存在于 C 中,而不存在于 C++(甚至 C++0x)中,除非作為特定于編譯器的擴展.
Note that restrict
only exists in C, not C++ (not even C++0x), except as a compiler-specific extension.
這篇關于const 正確性是否為編譯器提供了更多優化空間?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!