2017-03-21 15 views
1

ベクトルが常に連続したメモリストレージを提供する場合、コンパイラは空のstd :: stringsにどのようにメモリを割り当てますか?ベクトル内の文字列のメモリ割り当て

私は、プライベートメンバーとしてstd:stringでいくつかのクラスをプッシュしたベクトルを持っています。次に、ベクトルへの参照を別のメソッドへの引数として渡します。

文字列のデータは、ベクトルの連続配列から参照されるヒープ内の他の場所にありますか?

答えて

3

std::stringのメモリ割り当てはです。です。

内部的には、実際の文字列データが格納されるメモリブロックを指すポインタがあります。だから、std :: stringのためにメモリを割り当てることは、単純にポインタのためのスペース、size_tまたは何か、そしておそらく2つ以上のプリミティブを割り当てることの問題です。

あなたが例えばstd::vector<std::string>を持っている場合、彼らはいくつかの定数kのためだけkバイトごとだからベクトルがstd::string年代のためのスペースを割り当てるために、それは簡単です。文字列データはこの割り当てに関与しません。

1

この場合実際に何が起こるかの詳細は、使用している特定のSTL実装に大きく依存しています。

は、私の印象は、ほとんどの実装ベクトルと文字列で(非常に簡略化 )のようなものを用いて実装されていることである、と述べた:

template<typename T> 
class vector 
{ 
    //... 
    private: 
    T* _data; 
}; 

class string 
{ 
    private: 
    char _smallStringsBuffer[kSmallSize]; 
    char* _bigStringsBuffer; 
}; 

ベクトルのデータが動的容量に基づいて、ヒープ上に割り当てられています(これは、デフォルトで初期化されるとデフォルト値を持ち、要素をベクトルに追加する間に増加します)。

文字列のデータは、小さな文字列(実装依存の値が「小」)に対して静的に割り当てられ、文字列が大きくなると動的に割り当てられます。これは、いくつかの理由がありますが、主に小さな文字列をより効率的に処理できるようにするためです。 v._dataは、ヒープ上に割り当てられますのでベクトルvの基本的なデータは、スタックになります。この特定のケースで

void MyFunction(const vector<string>& myVector) 
{ 
    // ... 
} 

int main() 
{ 
    vector<string> v = ...; 

    // ... 

    MyFunction(v); 

    // ... 

    return 0; 
} 

あなたが説明した例のようなものです。 vの容量がNの場合、ヒープ内のv._dataのサイズはsizeof(string)* Nになります。ここで、文字列のサイズはkSmallSize * sizeof(char)+ sizeof(char *)に依存する定数です。上記の文字列の定義に基づいています。

連続したデータの場合、ベクトルで収集されたすべての文字列の文字数がkSmallSizeよりも少ない場合に限り、そのデータはメモリ内で「ほぼ」連続します。

これはパフォーマンスに重要なコードにとって重要な考慮事項ですが、実装の詳細は時間とともに変化する可能性があるため、ほとんどの人が標準的なSTLのベクトルと文字列に頼るとは思えませんプラットフォームとコンパイラ。さらに、コードが "高速"パスから外れると、レイテンシが急激に増加していることを確認するのが難しくなります。

関連する問題