web-dev-qa-db-ja.com

不変の文字列とstd :: string

私は最近、不変の文字列について読んでいます なぜ文字列をJava and .NET? で変更できないのですか? .NET Stringが不変なのはなぜですか? とその理由 [〜#〜] d [〜#〜 ] は不変の文字列を選択しました。多くの利点があるようです。

  • スレッドセーフ
  • より安全に
  • ほとんどのユースケースでより効率的なメモリ。
  • 安価な部分文字列(トークン化とスライス)

言うまでもなく、ほとんどの新しい言語には不変の文字列、D2.0、Java、C#、Pythonなどがあります。

C++は不変文字列の恩恵を受けますか?

これらの利点をすべて備えた不変の文字列クラスをc ++(またはc ++ 0x)で実装することは可能ですか?


更新:

不変文字列 const_string および fix_str には2つの試みがあります。どちらも半年で更新されていません。彼らも使用されていますか? const_stringがブーストにならなかったのはなぜですか?

61
deft_code

意見として:

  • はい、C++用の不変の文字列ライブラリが必要です。
  • いいえ、std :: stringを不変にしたくありません。

(標準ライブラリ機能として)本当に価値がありますか?私はそうは言いません。 constを使用すると、ローカルで不変の文字列が得られます。システムプログラミング言語の基本的な性質は、可変文字列が本当に必要であることを意味します。

23
anon

私の結論は、C++がconstのセマンティクスを持っているため、不変のパターンを必要としないということです。

Javaでは、Personクラスがあり、getName()メソッドで個人の_String name_を返す場合、唯一の保護は不変のパターンです。存在しない場合は、文字列を一晩中clone()する必要があります(通常の値オブジェクトではないが、保護する必要があるデータメンバーに関係するため)。

C++には、const std::string& getName() constがあります。したがって、SomeFunction(person.getName())のようなvoid SomeFunction(const std::string& subject)を記述できます。

  • コピーは行われませんでした
  • 誰かがコピーしたい場合、彼は自由にコピーできます
  • テクニックは文字列だけでなく、すべてのデータ型に適用されます
9
Notinlist

ここに決定的な答えがあるとは思わない。それは主観的なものです。個人的な好みのためではなく、少なくとも、最も頻繁に扱うコードのタイプのためです。 (それでも、貴重な質問です。)

メモリが安価な場合、不変の文字列は素晴らしいです。C++が開発されたとき、これは真実ではありませんでした。 (より制限されたプラットフォームでのOTOH CはC++よりもはるかに一般的であるため、引数は弱いです。)

C++で不変の文字列クラスを作成し、std::stringとほぼ互換性を持たせることができますが、専用の最適化と言語機能を備えた組み込みの文字列クラスと比較すると、まだ失われます。

std::stringは私たちが得る最高の標準文字列です。しかし、私はめったにそれを使用しません。 std::stringには、私の観点からは欠点が多すぎます

3
peterchen

確かにそれだけではありません。実際、Maxim Yegorushkinによる const_string ライブラリがあります。そして、ここにもう少し新しいライブラリがあります fix_str by Roland Pibinger。実行時に完全な文字列インターンがどれほど難しいかはわかりませんが、必要な場合はほとんどの利点を達成できます。

3
Cubbi
const std::string

行くぞ未定義の動作をさせたくない限り、文字列リテラルも不変です。

編集:もちろん、それは物語の半分にすぎません。 const文字列変数は、新しい文字列を参照させることができないため、役に立ちません。 C++ではPythonのような他の言語のように参照を再割り当てできないことを除いて、const文字列への参照はそれを行います。最も近いものは、動的に割り当てられた文字列へのスマートポインターです。

2
Mark Ransom

不変の文字列は素晴らしいif、新しい文字列を作成する必要があるときはいつでも、メモリマネージャは常にすべての文字列参照の所在を決定することができます。ほとんどのプラットフォームでは、このような機能の言語サポートは比較的低コストで提供できますが、そのような言語サポートが組み込まれていないプラットフォームでははるかに困難です。

たとえば、不変の文字列をサポートするx86でのPascal実装を設計する場合、文字列アロケーターがすべての文字列参照を見つけるためにスタックを歩くことができる必要があります。その唯一の実行時コストは、一貫性のある関数呼び出しアプローチを必要とするでしょう。末尾呼び出しを使用せず、すべての非リーフ関数にフレームポインターを保持させる]。 newで割り当てられた各メモリ領域には、文字列が含まれているかどうかを示すビットが必要であり、文字列を含むメモリ領域にはメモリレイアウト記述子へのインデックスが必要ですが、それらのコストはごくわずかです。

GCがスタックをウォークするテーブルではなかった場合、コードでポインターではなくハンドルを使用し、ローカル変数がスコープに入ったときにコードでストリングハンドルを作成し、スコープから外れたときにハンドルを破棄する必要があります。はるかに大きなオーバーヘッド。

1
supercat

Qtは、コピーオンライトで不変の文字列も使用します。
きちんとしたコンパイラでどれだけのパフォーマンスが得られるかについては、いくつかの議論があります。

0
Martin Beckett

定数文字列は値のセマンティクスではほとんど意味がなく、共有はC++の最大の強みの1つではありません...

0
fredoverflow