関数の引数にキーワードを使用するとパフォーマンスが向上することはわかっていconst
ますが、追加するのをいつも忘れています。コンパイラ (この場合は GCC) は、変数が関数中に変更されないことに気付き、const
明示的に追加したかのようにコンパイルするほどスマートですか?
5 に答える
についてよくある誤解がありconst
ます。オブジェクト を作成するだけでconst
は、その値は決して変更されないことを意味し、機能中だけでなく、変更されることもありません。
関数にパラメーターを作成しても、その値が決してconst
変わらないというわけではありません。関数がそのポインターを介してconst
値を変更できないことを意味するだけです。値は他の方法で変更できます。
たとえば、次の関数を見てください。
void f(const int* x, int* y)
{
cout << "x = " << *x << endl;
*y = 5;
cout << "x = " << *x << endl;
}
const
へのポインタを取ることに注意してくださいx
。ただし、次のように呼び出すとどうなりますか。
int x = 10;
f(&x, &x);
現在、ポインターf
がありconst
ますが、それは非 const オブジェクトへのものです。したがって、値は変更される可能性があり、同じオブジェクトへのポインターではないため変更y
されますconst
。これらはすべて、完全に合法的なコードです。ここには面白いビジネスはありません。
あなたの質問は完全に誤った前提に基づいているため、答えはありません。
コンパイラ (この場合は GCC) は、変数が関数中に変更されないことに気付き、明示的に const を追加したかのようにコンパイルするほどスマートですか?
必ずしも。例えば:
void some_function(int *ptr); // defined in another translation unit
int foo(int a) {
some_function(&a);
return a + 1;
}
コンパイラは何を行うかsome_function
を認識できないため、変更しないと想定することはできませんa
。
リンク時の最適化は、おそらくsome_function
実際に何が行われているかを確認し、それに応じて動作する可能性がありますが、この回答に関する限り、定義some_function
が利用できない最適化のみを検討します。
int bar(const int a) {
some_function((int*)&a);
return a + 1;
}
コンパイラは何some_function
が行われるかを認識できませんが、値が変化しないと想定することはできます。a
したがって、適用される最適化を行うことができます。おそらくa
、への呼び出し全体で呼び出し先保存レジスタに保持できsome_function
ます。おそらく、呼び出しの後ではなく呼び出しを行う前に戻り値を計算し、 zap しa
ます。some_function
を変更すると、プログラムは未定義の動作をするa
ため、コンパイラの POV からすると、これが発生すると、 に「正しい」値を使用するか「間違った」値を使用するかは問題になりませんa
。
したがって、この例では、a
const をマークすることにより、他の方法では知ることができない何かをコンパイラに伝えました。some_function
これは変更されません*ptr
。とにかく、それが変更された場合、プログラムの動作がどうであるかは気にしません。
int baz(int a) {
some_function(NULL);
return a + 1;
}
ここで、コンパイラは、標準に関する限り、関連するすべてのコードを確認できます。何が機能するかsome_function
はわかりませんが、にアクセスするための標準的な手段がないことは知っていますa
。したがって、const がマークされているかどうかa
に関係なく、コンパイラは変更されないことを認識しているため、違いはありません。
もちろん、デバッガーのサポートはこの状況を複雑にする可能性があります - 私は物事が と にどのように対応しているかはわかりませんがgcc
、gdb
少なくとも理論的には、コンパイラーがデバッガーを壊してa
手動で変更することをサポートしたい場合、コンパイラーはそれを変更不可能なものとして扱わないかもしれません. 同じことが、some_function
プラットフォーム固有の機能を使用してスタックをたどり、a
. プラットフォームはそのような機能を提供する必要はありませんが、提供すると最適化と競合します。
int
ローカル変数の作成に失敗した特定の最適化に失敗した gcc の古いバージョン (3.x、x を思い出せない) を見たことがありますconst
が、私の場合、gcc 4 は最適化を行いました。とにかく、私が考えているのはパラメータではなく、定数値で初期化された自動変数でした。
a
私が言ったことのいずれにおいても、パラメーターであることは特別なことではありません。関数で定義された任意の自動変数であってもかまいません。パラメータが定数値で初期化の効果を得る唯一の方法は、関数を定数値で呼び出し、コンパイラがその呼び出しの値を監視することです。これは、関数がインライン化されている場合にのみ発生する傾向があります。そのため、関数へのインライン呼び出しには、「アウト オブ ライン」関数本体が適さない追加の最適化が適用される可能性があります。