2

私は、メモリ使用量に関して可能な限り意地悪である必要があるプロジェクトに取り組んでいます。vector<bool>例のサイズの総合計サイズを計算しようとして32います:

vector<bool> v(32);
cout << "sizeof: " << sizeof(v) << endl;
cout << "size: " << v.size() << endl;
cout << "capacity: " << v.capacity() << endl;
cout << "max_size: " << v.max_size() << endl;

それは私に与える:

sizeof: 40                     <- 40 byte? wtf?
size: 32                       <- hoping an element takes up 1 bit
                                  (instead of the usual 1 byte for booleans)
                                  this should take around 32 bit memory
capacity: 64                   <- I guess this is because minimum size is
                                  1 integer = 64 bit
max_size: 9223372036854775744  <- relevant somehow?

私の64ビットubuntu 12.04マシンで。だから私は次のようにメモリを計算できると思った:

40 * 8 + 64 * 1 = 384 bit = 48 byte

したがって、この計算によると、ほとんどのメモリは size のベクトル オブジェクトに費やされます32。私の質問は、なぜvectorオブジェクトがそれほど多くのメモリを使用する必要があるのですか? また、私の計算に間違いはありますか?周りのベクトルサイズに対して自分でビット単位の操作を行わずに効率を上げるにはどうすればよい32ですか?

4

6 に答える 6

4

これらの 40 バイトは管理上のオーバーヘッドです。とりわけ、 aはそのandvectorを追跡する必要があり(すでに 2 バイト分が失われています)、非常に重要なのは、実際のデータへのポインターです!sizecapacitysize_t

ベクトルによって保持される実際のデータは、デフォルトのベクトル アロケータによってヒープに割り当てられます。そのメモリ消費量は の結果には含まれませんsizeof

于 2013-02-27T14:42:40.873 に答える
3

sizeof(v)vのデータのサイズではなく、 の構造のサイズを取得していvます。それはやっているようなものです:

struct S { int* x };

S s;
s.x = new int[10000];

sizeof(s); // only the size of int* (it doesn't/can't check how much data is allocated)

std::vector<bool>よりも大きな構造サイズを持つ理由については、バージョンが特殊化std::vector<int>されていることを思い出してください。boolビットごとの記録を保持するために、いくつかの追加メンバーが必要です。

于 2013-02-27T14:40:41.113 に答える
1
  • v.size()に格納できる要素の数を返しますvector。メモリサイズとは直接関係ありません
  • v.capacity()ベクトルに割り当てられたメモリ セルの量を返します。ベクトルは事前にいくつかのメモリを割り当てますが、すべてが最初にアクセスできるわけではありません。メモリサイズに直接関係しない
  • sizeof(v)構造体自体のバイト単位のサイズを取得しています。いくつかの指針がここにあると思います。サイズ可変なども同様です。

ベクトルの要素が取っているメモリを取得したい場合は、おそらくこれが最も近い式になります。v.size() * sizeof(v[0])

于 2013-02-27T14:41:57.130 に答える
1

That's the price you pay for a dynamically re-sizable structure. What's returned by sizeof(v) is actually just the overhead for the vector to keep track of the dynamically allocated memory where it stores its data. The space for storing the data is not included in that number.

If you know the number of items at compile time, you can use std::bitset instead. std::bitset actually will use 1 bit per boolean you store (rounded up to the word size it uses) without the overhead of std::vector.

于 2013-02-27T14:51:09.320 に答える
1

g++ 実装のソースを見ると、次のメンバーが見つかります。

vector は _Bvector_impl _M_impl から継承します。

継承された _Bvector_impl から

_Bit_iterator   _M_start;   16 bytes
_Bit_iterator   _M_finish;  16 bytes
_Bit_type*  _M_end_of_storage;  8 bytes

これは合計で 40 バイトになります。

_Bit_iterator が含まれています

_M_offset, an unsigned int: 8 bytes
_M_p,      a pointer 8 bytes. 
于 2013-02-27T14:49:00.057 に答える
1

your のサイズがstd::vectorコンパイル時に実際に固定されている場合は、std::array代わりに a を使用するのが理にかなっています。配列にはオーバーヘッドがありません(ただし、パディングがあります)。

ただし、 の非常に特殊なケースではbool、 を考慮する必要がありますstd::bitset。Abitsetはそのサイズによってパラメーター化さboolれ、可能な限り効率的になるようにパックされます。トグルされたビットのカウントを保持するため、(自分で作成するよりも) パックされた配列ほどメモリ効率が良くありません。

liveworkspaceでのデモ:

#include <bitset>
#include <array>
#include <vector>

#include <iostream>

int main() {
   std::vector<bool> vec(32);
   std::array<bool, 32> arr;
   std::array<uint8_t, 4> packed;
   std::bitset<32> bs;

   std::cout << "vector: " << sizeof(vec) + vec.capacity()/8 << "\n";
   std::cout << "array : " << sizeof(arr) << "\n";
   std::cout << "packed: " << sizeof(packed) << "\n";
   std::cout << "bitset: " << sizeof(bs) << "\n";
}

与えます:

vector: 48
array : 32
packed: 4
bitset: 8

明らかpackedに最も効率的なコンテナですがbitset、非常に低コストで既製のコンテナを提供します (64 ビット マシンのポインタと同じくらいのスペース)。

于 2013-02-27T14:55:01.137 に答える