3

sizeof()いくつかの C++ 標準ライブラリ クラスに興味を持ち、演算子を適用しました。これが私が観察したことです:

int main() 
{
    vector<double> v1;
    set<double> s1;
    map<double,double> m1;

    stack<char> st;
    queue<char> q;

    vector<char>  v2;
    set<char> s2;
    map<char,char> m2;

    cout<<sizeof(v1)<<" "<<sizeof(s1)<<" "<<sizeof(m1)<<endl;
    cout<<sizeof(v2)<<" "<<sizeof(s2)<<" "<<sizeof(m2)<<endl;
    cout<<sizeof(q)<<" "<<sizeof(st)<<endl;
    return 0;
}

私のシステム(64ビット)での出力は次のとおりです。

12 24 24
12 24 24
40 40

std::set実装に赤黒木を使用していることは知っています。したがって、バイナリ ツリーの各ノードには 2 つのポインター (それぞれ 8 バイト) があり、値 (8 バイト、合計 24) は問題ないようです。

  1. std::map(Red-Black ツリーも使用) には追加のキーがありますが、それでも 24 バイトですか? なんで?

  2. 12バイトしかかからないのにstd::queue、なぜstd::stack40バイトかかるのですか?std::vector

  3. charクラスのサイズに影響しdoubleないのはなぜですか? テンプレのせい?

4

5 に答える 5

6

これらのクラスの実装はブラック ボックスであり、含まれるデータまたはプライベート メンバーを知る方法はありません。それは完全に実装次第です。

オブジェクト インスタンス内のすべてのバイトが何であるかを知る唯一の方法は、ソース コードを読むことです。

于 2013-07-04T14:35:32.497 に答える
5

オペレーターが型のsizeofサイズを教えてくれます。

ここで、非常に単純化されたバージョンを作成する場合std::vector<T>(これは REAL の実装ほど何もしないことに注意してください。また、単純化されすぎて実際に機能することはありません。実際のものが本当に必要です):

template<typename T>
class vector<T>
{
   public:
      typedef size_t size_type;
   private:
     T* mdata;
     size_type msize;
     size_type mreserved;
   public:
     vector() { mreserved = msize = 0; mdata = 0; }
     vector(size_type sz) { msize = 0; mreserved = sz; mdata = new T[sz](); }
     void push_back(const T& v) 
     { 
        if (msize + 1 > mreserved) grow(mreserved * 2);
        mdata[msize+1] = v;
        msize++;
     }
     size_type size() const { return msize; }
     // bunch of other public functions go here. 
   private:
     void grow(size_type newsize)
     {
        if (newsize < 8) newsize = 8;
        T* newdata = new T[newsize]; 
        for(size_type i = 0; i < msize; i++) newdata[i] = mdata[i];
        swap(mdata, newdata);
        delete [] mdata;
        mreserved = newsize;
     }
  };

ご覧のとおり、実際のクラスのサイズは、格納されているデータ セットがどれだけ大きくても同じです (同じサイズと同じ要素数が含まれています)。つまり、sizeof(vector<int>)は一定です。背後に格納されているデータのサイズはmdataもちろん変化していますが、それsizeofはわかりません (わかりません)。

于 2013-07-04T14:59:04.623 に答える
4

このサンプル ソース コードから、次のことがわかります。

struct A
{
    int* p; //4 bytes
    A(int n)
    {
        p = new int[n];
    }  
};

int main()
{
    A x1(10);   
    A x2(100);  
    cout << boolalpha << (sizeof(x1) == sizeof(x2)); //prints true
}

その理由は、 A にはポインターしか含まれていないためです。ポインターのサイズは常に同じです (通常は 4)。ポインターが何を指すかは問題ではありません - 1000 または 1000000 の動的配列です。それでも 4 です。

char へのポインターは double へのポインターと同じサイズであるため、Char または double はサイズに影響しません。

ポインタではなく実際に配列を保持する std::array の場合、これらは重要です (配列の型とサイズの両方)。

cout << boolalpha << ((sizeof(std::array<int, 10>) == sizeof(std::array<int, 11>)); //false!
cout << boolalpha << ((sizeof(std::array<int, 10>) == sizeof(std::array<long double, 10>)); //false!
于 2013-07-04T14:48:43.690 に答える
2

sizeof はコンパイル時に評価されることを覚えておくことが重要です。つまり、動的ではありません。

その仕事は、クラス/構造体/単純な古いデータのサイズを返すことです。他には何もありません。

そのため、ベクトル、セット、およびマップに対して常に同じ結果が得られます。

于 2013-07-04T14:37:40.183 に答える
2

コンテナー クラスのサイズは、消費される要素の数に応じて増加する可能性があると想定しているようですが、すべての型のサイズが固定されているため、これは物理的に不可能です。

代わりに、要素は動的割り当てを使用して間接的に格納されます。
sizeof は、この情報をあなたに開示しません

提供される唯一の情報sizeofは、コンテナーの構築と管理で使用されるポインター、カウンター、フラグ、およびその他のメタデータの数です。この種の詳細は抽象化されており、決して合理化しようとしないでください。

于 2013-07-04T14:46:27.320 に答える