2012-01-10 21 views
3

私は基本的な文字列の実装のいくつかと少し混乱しています。私は内側の作業を理解し、新しいことを学ぶためにソースを調べてきました。私はメモリがどのように管理されているかを完全に把握することはできません。std :: string allocation policy

基本文字列実装

  • からわずかいくつかの一口生アロケータは、割り当てられたバッファ__size内担当者が置かれ割り当てるときに算出され... char型

    typedef typename _Alloc::template rebind<char>::other _Raw_bytes_alloc; 
    
  • するためのものです文字にも合うように

    size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); 
    void* __place = _Raw_bytes_alloc(__alloc).allocate(__size); 
    _Rep *__p = new (__place) _Rep; 
    
  • これは、文字の設定文字データが_Repバッファからフェッチする方法

    _CharT* _M_refdata() throw() 
    { 
        return reinterpret_cast<_CharT*>(this + 1); 
    } 
    
  • ある - 私を悩ませているどのような方法の1種類

    _M_assign(__p->_M_refdata(), __n, __c); 
    

のために生のことですアロケータはchar型ですが、割り当てられたメモリには_Repオブジェクトと文字データ(char型である必要はありません)が格納されます。

また、なぜ文字データの開始(または終了)は、バッファ内にあるところES _M_refdataへの呼び出しが知っている(すなわちthis+1

編集:this+1はちょうど_Repオブジェクトの後に次の位置に内部ポインタをプッシュしていますか?

私はメモリアライメントとキャストの基本的な理解がありますが、これは私が読んだことを超えているようです。

誰かが助けてくれますか、より有益な読書資料を指摘できますか?

答えて

0

アロケータは、Cのmallocのように、オブジェクトではなくバイトへのポインタを返します。戻り値の型はchar *またはvoid *です。

CおよびC++標準のどこかに、charと他のオブジェクトタイプの間の再解釈キャストを明示的に許可する句があります。これは、Cはオブジェクトをバイト配列(ディスクやネットワークソケットに書き込むときのように)で扱う必要があり、バイト配列をオブジェクトとして扱う必要があるからです(メモリの範囲やディスクからの読み込み時など)。エイリアシングおよび最適化の問題から保護するために

、あなたは異なるタイプのオブジェクトに同じchar *をキャストする許可されていないとあなたがオブジェクト型にchar *をキャストしたら、あなたは、オブジェクトのを修正することはできませんバイトに書き込むことによって値を返します。

+0

これは 'char'とは関係ありません。すべての単純なポインタ型を相互に 'reinterpret_cast 'することができます。 – filmor

+4

@filmor:not true。これは厳密なエイリアシング規則に違反します。 –

+0

@filmor:あなたはそれをやりますが、それをコンパイルしてあなたがするべきことをすると約束しません。例えば、 'char *'を 'double'にキャストした後、doubleをレジスタにロードするかもしれません。次に、 'char *'に何かを書きます。 'double'の値を変更することはありません。 –

4

新しいプレースメントがありません。ライン

_Rep *__p = new (__place) _Rep; 

__placeで新しい_Rep -objectを初期化します。これのためのスペースは既に以前に割り当てられています(つまり、プレースメントnewはそれ自体では割り当てられませんが、実際はコンストラクタ呼び出しのみです)。

CおよびC++のポインター演算では、this + 1sizeof(*this)バイトの右辺がthisのポインターであることがわかります。前に(__capacity + 1) * sizeof(_CharT) + sizeof(_Rep)バイトが割り当てられているので、文字データには_Repオブジェクトの後のスペースが使用されます。したがって、レイアウトは次のようになります。

| _Rep | (__capacity + 1) * _CharT | 
関連する問題