2013-07-04 67 views
3

我很好奇並在某些C++標準庫類上應用sizeof()運算符。以下是我觀察到: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採用紅黑樹的實現。因此,二叉樹的每個節點都有兩個指針(每個8個字節),值(8個字節,共24個)似乎沒問題。

  1. std::map(同樣採用紅黑樹)有一個額外的鑰匙,但還是24個字節?爲什麼?

  2. 爲什麼std::queuestd::stack需要40個字節,而std::vector只需要12個字節?

  3. 爲什麼chardouble不影響類的大小?是因爲模板嗎?

+3

'sizeof'不是一個函數,而是一個在C++語言中定義的運算符和關鍵字。 –

+0

@BasileStarynkevitch我更新了問題 – banarun

+2

爲什麼你會期望'sizeof(container)== sizeof(node)'? –

回答

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不知道(不知道)。

6

這些類的實現是黑盒子,沒有辦法告訴它們包含哪些數據或私有成員。這完全取決於實施。

要知道對象實例中所有字節的唯一方法是讀取源代碼。

+0

無論是私人還是公共成員,sizeof()都不會告訴該類的大小? – banarun

+0

@banarun:是的,它的確如此。 –

+1

@banarun是的,'sizeof'返回所有成員的大小,但你不知道它們是什麼。僅僅因爲一個類有24個字節的大小並不意味着它有3個指針。 –

2

重要的是要記住,sizeof在編譯時評估:所以它在任何意義上都不是動態的。

它的工作是返回類/結構/普通舊數據的大小;沒有其他的。

這就是爲什麼它總是給你的向量,集合和地圖相同的結果。

2

您似乎認爲容器類的大小可以隨着元素消耗的數量而增加,但這在物理上是不可能的,因爲所有類型都具有固定的大小。

而是使用動態分配間接存儲元素;
sizeof不會向您顯示此信息

只有sizeof給出的信息是在容器的構建和管理中使用了多少指針,計數器,標誌和其他元數據;這種細節是從你身上抽象出來的,你不應該試圖對它進行合理化。

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 
} 

的原因是,只有一個指標。指針的大小始終相同(通常爲4)。指針指向什麼並不重要 - 一個1000或1000000的動態數組。它仍然是4。

Char或double不影響大小,因爲指向char的指針與指向double的指針的大小相同。

對於性病::陣列,其實際持有的陣列,而不是一個指針,這些會事宜(包括數組類型和尺寸):

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!