const の正確さにより、コンパイラーの最適化の余地が広がりますか? [重複] 質問する

const の正確さにより、コンパイラーの最適化の余地が広がりますか? [重複] 質問する

プログラムの読みやすさが向上し、エラーが発生しにくくなることはわかっていますが、パフォーマンスはどの程度向上するのでしょうか?

ところで、参照とconstポインタの主な違いは何でしょうか? メモリへの格納方法が異なっていると思いますが、どのような違いがあるのでしょうか?

ベストアンサー1

[編集: さて、この質問は私が最初に考えていたよりも微妙です。]

const へのポインターまたは const の参照を宣言しても、コンパイラーによる最適化にはまったく役立ちません。(ただし、この回答の下部にある更新を参照してください。)

宣言constは、識別子が範囲宣言の; 基になるオブジェクトが変更できないとは言いません。

例:

int foo(const int *p) {
    int x = *p;
    bar(x);
    x = *p;
    return x;
}

コンパイラは、*pが の呼び出しによって変更されないと想定することはできません。は (たとえば) グローバル int へのポインターである可能性があり、それを変更する可能性があるbar()ためです。pbar()

コンパイラが の呼び出し元foo()と の内容について十分に知っていて、 がを変更しないことをbar()証明できる場合、bar()*pconst宣言なしでも証明は実行できる。

しかし、これは一般的には当てはまります。 はconst宣言のスコープ内でのみ効果があるため、コンパイラーは、そのスコープ内でポインターまたは参照をどのように処理しているかをすでに把握しており、基になるオブジェクトを変更していないこともすでに認識しています。

つまり、constこのコンテキストで行われることは、間違いを防ぐことだけです。コンパイラーに、すでにわかっていること以外のことは何も伝えないので、最適化には関係ありません。

を呼び出す関数についてはどうでしょうかfoo()? たとえば:

int x = 37;
foo(&x);
printf("%d\n", x);

コンパイラは、foo()が を取るので、これが 37 を出力することを証明できますかconst int *?

いいえ。constへのポインタを取ってもfoo()、const性を捨ててintを変更する可能性があります。(これはない未定義の動作です。) ここでも、コンパイラは一般に何らかの仮定を行うことはできません。また、コンパイラがfoo()そのような最適化を行うのに十分な知識を持っている場合は、 がなくても であることがわかりますconst

最適化が許可されるのは、次のような場合のみconstです。

const int x = 37;
foo(&x);
printf("%d\n", x);

ここで、何らかのメカニズムを通じて を変更するとx(たとえば、 へのポインタを取得して をキャストするなどconst)、未定義の動作が発生します。したがって、コンパイラは、 が変更されていないと想定して、定数 37 を printf() に伝播できます。この種の最適化は、 を宣言するすべてのオブジェクトに対して有効ですconst。 (実際には、参照を取得しないローカル変数は、そのスコープ内で変更されているかどうかをコンパイラがすでに認識しているため、メリットはありません。)

あなたの「補足」の質問に答えると、(a) const ポインタはポインタであり、(b) const ポインタは NULL に等しい可能性があります。内部表現 (つまり、アドレス) はおそらく同じであるというのは正しいです。

[アップデート]

としてクリストフコメントで指摘されているように、私の回答は について言及していないため不完全ですrestrict

C99標準のセクション6.7.3.1(4)には次のように書かれています。

B の実行中、L は P に基づく &L を持つ任意の lvalue とします。L を使用して、それが指定するオブジェクト X の値にアクセスし、X も (何らかの方法で) 変更される場合、次の要件が適用されます。T は const 修飾されてはなりません。...

(ここで、B は、T への制限ポインターである P がスコープ内にある基本ブロックです。)

したがって、C 関数がfoo()次のように宣言されている場合:

foo(const int * restrict p)

...そしてコンパイラ5月*pの存続期間中p、つまり の実行中には変更が行われないと想定しますfoo()。そうでない場合、動作は未定義になります。

したがって、原理的には、restrictconst へのポインターと組み合わせると、上で却下された両方の最適化が有効になります。実際にこのような最適化を実装しているコンパイラはあるのでしょうか? (少なくとも GCC 4.5.2 では実装されていません。)

restrictコンパイラ固有の拡張機能を除き、これは C にのみ存在し、C++ (C++0x も) には存在しないことに注意してください。

おすすめ記事