繁体   English   中英

C ++标准库上的sizeof()

[英]sizeof() on C++ Standard Library

我很好奇并在一些C ++标准库类上应用了sizeof()运算符。 这是我观察到的:

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使用Red-Black树来实现。 所以二叉树的每个节点都有两个指针(每个8个字节),值(8个字节,总共24个)似乎没问题。

  1. std::map (也使用Red-Black树)有一个额外的键,但仍然是24个字节? 为什么?

  2. 为什么std::queuestd::stack占用40个字节,而std::vector只占用12个字节?

  3. 为什么chardouble不会影响类的大小? 是因为模板吗?

这些类的实现是一个黑盒子,没有办法告诉它们包含哪些数据或私有成员。 这完全取决于实施。

了解对象实例中所有字节的唯一方法是读取源代码。

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

此示例源代码将为您提供以下想法:

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!

重要的是要记住sizeof 在编译时进行评估 :因此它在任何意义上都不是动态的。

它的工作是返回类/结构/普通旧数据的大小; 没有其他的。

这就是为什么它总是为你的矢量,集合和地图提供相同的结果。

您似乎假设容器类的大小可以随着消耗的元素数量而增加,但这在物理上是不可能的,因为所有类型都具有固定大小。

而是使用动态分配间接存储元素;
sizeof 不会向您透露此信息

sizeof给你的唯一信息是在容器的构造和管理中使用了多少指针,计数器,标志和其他元数据; 这种细节是从你身上抽象出来的,你永远不应该试图对它进行合理化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM