IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

std::string まとめ

注意

gcc version 4.3.2 の std::string 私的まとめ

実装

  • クラス std::basic_string::_Rep は以下の情報を持つ
    • 文字列長 _M_length
    • 確保された容量 _M_capacity
    • 参照カウンタ _M_refcount
  • アロケータ(std::basic_string::_Alloc)の派生クラス(std::basic_string::_Alloc_hider)が文字列へのポインタをメンバとして持つ(_M_p)
    • アロケータは空のクラスであることが多く、そのための 1byte の容量を節約するため(empty base optimization)
  • std::basic_string のメンバは std::basic_string::_Alloc_hider のインスタンス _M_dataplus だけ
    • つまり、 sizeof(std::string) == sizeof(char*) 無駄がない。
  • std::basic_string::_Rep は _M_dataplus._M_p が指している領域の前に確保されている(_M_dataplus._M_p を std::basic_string::_Rep にキャストして 1 を引いた場所に確保されている)

参照カウンタの3つの状態

参照カウンタには3つの状態がある

  1. 共有不可能
  2. 共有可能
  3. 共有中
共有不可能

非 const なイテレータを返す操作や、文字のリファレンスを返す操作を行ったとき(begin, end, insert, operator[]) に、共有不可能なオブジェクトになる。
ポインタを外部に漏らした瞬間、そのメモリは共有できないものになるということ。
共有不可能なオブジェクトは、常にコピーが行われる。
const な文字列は共有不可能なオブジェクトにはならない。

std::string a("hoge");
const std::string b("fuga");

a.begin(); // ここで、 a は共有不可能なオブジェクトになる

b.begin(); // const なら大丈夫

また、 reallocate が発生するような処理が発生したとき、また共有可能なオブジェクトに戻る。

共有可能

代入によってコピーが行われない。まだ共有されていない文字列。初期状態の文字列。

共有中

文字列データが他のオブジェクトと共有され、参照カウンタによって管理されている。