myObj.setType( "fluid");のような関数を呼び出すと プログラムで何度も、文字通りの「流体」のコピーがいくつメモリに保存されますか?コンパイラは、このリテラルがすでに定義されていることを認識し、それを再度参照できますか?
6 に答える
これはC++(言語)とは何の関係もありません。代わりに、コンパイラーが実行できるのは「最適化」です。したがって、使用しているコンパイラ/プラットフォームに応じて、「はい」と「いいえ」の答えが返されます。
@Davidこれは言語の最新ドラフトからのものです:
§2.14.6(28ページ)
すべての文字列リテラルが異なるかどうか(つまり、重複しないオブジェクトに格納されるかどうか)は、 実装によって定義されます。文字列リテラルを変更しようとした場合の影響は未定義です。
強調は私のものです。
つまり、文字列リテラルの変更は未定義の動作であるため、C++の文字列リテラルは不変です。したがって、コンパイラは無料で、冗長なコピーを排除します。
ところで、私はC ++についてのみ話している;)
はい、できます。もちろん、それはコンパイラに依存します。VC ++の場合、構成可能です。
http://msdn.microsoft.com/en-us/library/s0s0asdt(VS.80).aspx
はい、できますが、そうなるという保証はありません。確実にしたい場合は、定数を定義してください。
これはコンパイラの実装の問題です。私が使用した多くのコンパイラには、重複する文字列リテラルを共有またはマージするオプションがあります。重複する文字列リテラルを許可すると、コンパイルプロセスが高速化されますが、実行可能ファイルが大きくなります。
2.13.4 / 2:「すべての文字列リテラルが異なる(つまり、重複しないオブジェクトに格納されている)かどうかは、実装によって定義されます」。
これにより、求めている最適化が可能になります。
余談ですが、少なくとも標準のそのセクション内では、わずかなあいまいさが存在する可能性があります。文字列リテラルの定義では、次のコードで1つの文字列リテラルを2回使用するのか、2つの文字列リテラルをそれぞれ1回使用するのかがはっきりしません。
const char *a = "";
const char *b = "";
しかし、次の段落では、「翻訳フェーズ6では、隣接する狭い文字列リテラルが連結されます」と述べています。何かがそれ自体に隣接している可能性があるという意味でない限り、このコードがフェーズ6で連結された2つの文字列リテラルを使用する意図はかなり明確だと思います。したがって、1つの文字列リテラルが2回ではありません。
const char *c = "a" "a";
それでも、「a」と「a」が同じ文字列リテラルであることを読んだ場合、標準では、話している最適化が必要です。しかし、それらは同じリテラルではないと思います。たまたま同じ文字で構成されている異なるリテラルだと思います。これはおそらく、標準の他の場所、たとえば文法と構文解析に関する一般的な情報で明らかにされています。
明確にされているかどうかにかかわらず、多くのコンパイラー作成者は標準を私が思うように解釈しているので、私も正しいかもしれません;-)
C / C ++では、その場合の処理は指定されていないと思いますが、ほとんどの場合、その文字列の複数の定義を使用します。