const-correctness はコンパイラに最適化の余地を与えるか?
質問
可読性が向上し、プログラムがエラーになりにくくなることはわかりましたが、性能はどの程度向上するのでしょうか?
ついでに言うと、参照と
const
のポインタはどう違うのでしょうか?メモリへの格納方法が違うと思うのですが、どうなんでしょう?
どのように解決するのですか?
[編集: OK、この質問は私が最初に考えたよりも微妙です]。
pointer-to-constまたはreference-of-constを宣言することは、コンパイラが何かを最適化するのに役立つことはありません。 (この回答の一番下にある更新を参照してください)。
また
const
の中で識別子がどのように使われるかを示すだけです。
スコープ
宣言は、その宣言のスコープ内で識別子がどのように使用されるかを示すだけであり、基盤となるオブジェクトが変更できないことを示すものではありません。
例です。
int foo(const int *p) {
int x = *p;
bar(x);
x = *p;
return x;
}
コンパイラは
*p
への呼び出しによって変更されないと仮定することはできません。
bar()
というのは
p
は(例えば)グローバルなintへのポインタである可能性があり
bar()
はそれを修正するかもしれません。
の呼び出し元についてコンパイラが十分に知っている場合、 その呼び出し元は
foo()
の内容を知っていて
bar()
を証明することができます。
bar()
を変更しない
*p
であれば
は、const 宣言がなくてもその証明を行うことができます。
.
しかし、これは一般的に言えることです。 なぜなら
const
は宣言のスコープ内でのみ効果を持つため、コンパイラはそのスコープ内でポインタや参照をどのように扱っているかをすでに見ることができます。つまり、根本的なオブジェクトを変更していないことをすでに知っているのです。
ですから、要するに、すべての
const
は間違いを防いでくれるのです。 コンパイラがまだ知らないことは何も教えてくれませんので、最適化には無関係です。
を呼び出す関数についてはどうでしょうか?
foo()
? のように。
int x = 37;
foo(&x);
printf("%d\n", x);
コンパイラはこれが 37 と表示されることを証明できますか?
foo()
は
const int *
?
いいえ、たとえ
foo()
がconstへのポインタを取るとしても、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-qualifiedであってはならない。...
(ここでBは、TへのリストリクトポインタであるPがスコープ内にある基本ブロックである)
ですから、もしCの関数
foo()
はこのように宣言されます。
foo(const int * restrict p)
...すると、コンパイラが
は
を修正しないものとします。
*p
が生きている間は
p
-- すなわち、実行中に
foo()
-- の実行中です。そうでなければ動作が未定義になってしまうからです。
ですから、原理的には
restrict
をpointer-to-constと組み合わせることで、上で却下された最適化の両方が可能になります。 実際にそのような最適化を実装しているコンパイラはあるのでしょうか? (少なくとも GCC 4.5.2 はそうではありません)。
以下のことに注意してください。
restrict
は C 言語にのみ存在し、C++ には存在しません (C++0x にも存在しません)。
関連
-
[解決済み】識別子 "string "は未定義?
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] Collatz予想の検証を行うC++のコードは、なぜ手書きのアセンブリよりも高速に動作するのでしょうか?
-
[解決済み] mutable' キーワードには、const 関数で変数を変更できるようにする以外の目的があるのでしょうか?
-
[解決済み] リファレンスとポインタの使い分け
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み] なぜ 'this' はポインターで、参照ではないのですか?
-
[解決済み] volatile int * p "のような揮発性ポインタはなぜ有用なのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】構造体のベクター初期化について
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み] クラスにデフォルトコンストラクタが存在しない。
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み】Eclipse IDEでC++エラー「nullptrはこのスコープで宣言されていません」が発生する件
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む