std::string
は、より小さいサイズの文字列から再割り当てされた場合、割り当てられたメモリを自発的に返しませんか?
言い換えると:
std::string str = "Some quite long string, which needs a lot of memory";
str = "";
str = "A new quite long but smaller string"; // Guaranteed to not result in a heap allocation?
ヒープの断片化を避けるためにこれに依存しているので、私は尋ねます。
[string.cons]/36
は、移動割り当てに関してconst char*
にstd::string
を割り当てることを定義します。定義は次のとおりです。
[string.cons]/32
basic_string& operator=(basic_string&& str) noexcept(/*...*/)
Effects:反復子、ポインター、参照が無効になる場合を除き、割り当てをシーケンスコンテナーとして移動します。
これは、委員会が、実装に無効化操作とより保守的な操作を自由に選択させることを示しています。そして、物事をさらに明確にするために:
[basic.string]/4
basic_string
シーケンスの要素を参照する参照、ポインター、および反復子は、そのbasic_stringオブジェクトの次の使用によって無効になる場合があります。
- (4.1)非const
basic_string
への参照を引数として取る標準ライブラリ関数への引数として。- (4.2)
operator[]
、at
、data
、front
、back
、begin
、rbegin
、end
、およびrend
を除く非定数メンバー関数の呼び出し。
ヒープの断片化を避けるためにこれに依存しているので、私は尋ねます。
std::string
は、テンプレートパラメータとしてアロケータを取ります。ヒープの断片化の可能性に本当に関心がある場合は、独自のコードを作成できます。これには、いくつかのヒューリスティックを使用して、ニーズに合った割り当て戦略を設定できます。
実際には、私が知っているほとんどの実装は、あなたの質問の場合にメモリを再割り当てしません。これは、実装ドキュメントと最終的にソースコードをテストまたは確認することで確認できます。
CPPリファレンス は、charへのポインターへの割り当てを示しています
* this = basic_string(s)のようにsが指すヌル終了文字列の内容で内容を置き換えます。これにはTraits :: length(s)の呼び出しが含まれます。
この「あたかも」は実際には右辺値の割り当てに要約されるため、次のシナリオは非常に可能です。
文字列が短く(コンパイラ/ std libに応じて最大15または22バイト)、C++ 11以降のモードで比較的最近のコンパイラを使用している場合は、 短い文字列の最適化 (SSO)。この場合、文字列の内容はヒープに個別に割り当てられません。
このリンクには、一般的な実装と割り当て戦略に関する多くの詳細も含まれています。
ただし、例の両方の文字列はSSOには長すぎます。