0

関数の引数にキーワードを使用するとパフォーマンスが向上することはわかっていconstますが、追加するのをいつも忘れています。コンパイラ (この場合は GCC) は、変数が関数中に変更されないことに気付き、const明示的に追加したかのようにコンパイルするほどスマートですか?

4

5 に答える 5

4

についてよくある誤解があり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。これらはすべて、完全に合法的なコードです。ここには面白いビジネスはありません。

あなたの質問は完全に誤った前提に基づいているため、答えはありません。

于 2013-01-31T14:28:58.373 に答える
3

コンパイラ (この場合は 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

したがって、この例では、aconst をマークすることにより、他の方法では知ることができない何かをコンパイラに伝えました。some_functionこれは変更されません*ptr。とにかく、それが変更された場合、プログラムの動作がどうであるかは気にしません。

int baz(int a) {
    some_function(NULL);
    return a + 1;
}

ここで、コンパイラは、標準に関する限り、関連するすべてのコードを確認できます。何が機能するかsome_functionはわかりませんが、にアクセスするための標準的な手段がないことは知っていますa。したがって、const がマークされているかどうかaに関係なく、コンパイラは変更されないことを認識しているため、違いはありません。

もちろん、デバッガーのサポートはこの状況を複雑にする可能性があります - 私は物事が と にどのように対応しているかはわかりませんがgccgdb少なくとも理論的には、コンパイラーがデバッガーを壊してa手動で変更することをサポートしたい場合、コンパイラーはそれを変更不可能なものとして扱わないかもしれません. 同じことが、some_functionプラットフォーム固有の機能を使用してスタックをたどり、a. プラットフォームはそのような機能を提供する必要はありません、提供すると最適化と競合します。

intローカル変数の作成に失敗した特定の最適化に失敗した gcc の古いバージョン (3.x、x を思い出せない) を見たことがありますconstが、私の場合、gcc 4 は最適化を行いました。とにかく、私が考えているのはパラメータではなく、定数値で初期化された自動変数でした。

a私が言ったことのいずれにおいても、パラメーターであることは特別なことではありません。関数で定義された任意の自動変数であってもかまいません。パラメータが定数値で初期化の効果を得る唯一の方法は、関数を定数値で呼び出し、コンパイラがその呼び出しの値を監視することです。これは、関数がインライン化されている場合にのみ発生する傾向があります。そのため、関数へのインライン呼び出しには、「アウト オブ ライン」関数本体が適さない追加の最適化が適用される可能性があります。

于 2013-01-31T15:59:58.083 に答える