为什么当我向一个向量中添加元素时,它的大小是一样的?

Why does a vector have the same size when I add elements to it?

本文关键字:一样 添加 一个 为什么 向量 元素      更新时间:2023-10-16

我有这样的c++结构:

typedef unsigned long T;
struct Node {
    T index;
    T length;
    Node(): index(0), length(0), next(0) {}
    Node(const T &ind, const T &len): index(ind), length(len), next(0) {}
    vector<Node*> next;
};

我想知道下一个将占用多少内存。我知道它最多有五个元素。我是这样做的:

int main(int argc, const char * argv[]) {
    Node n;
    Node* x = new Node(3, 4);
    cout << "An empty vector of pointers: " << sizeof(n.next) << " bytesn";
    // Add five elements
    for(int i = 0; i < 5; i++)
        n.next.push_back(x);
    cout<< "New size of the vector of pointers: " << n.next.size() << " elementsn";
    cout<< "New size of the vector of pointers: " << sizeof(n.next)  << " bytesn";
    return 0;
}

下面是我的输出:

An empty vector of pointers: 24 bytes
New size of the vector of pointers: 5 elements
New size of the vector of pointers: 24 bytes

我的问题:怎么可能一个空向量需要24个字节,但相同的向量有5个元素在它仍然需要24个字节?它不应该占用更多的内存吗?像*24 + 5 * sizeof(Node*)*?

Vector是一个动态结构体,具有固定的"footprint",通常包含指向动态分配数据的指针。

n.next.size()返回动态分配数据的大小。sizeof(n.next)返回固定占用空间的大小。

给定类型的所有对象大小相同,sizeof(n.next)sizeof(vector<Node*>)等效。

vector实例不包含元素,它只指向它们,所以实例本身总是相同的大小。

它的工作原理是这样的:

class A
{
public:
    A(int n) : p(new char[n]), s(n) {}
    int size() const { return s; }
private:
    char* p;
    int s;
};
int main()
{
    A a(1);
    A b(100);
    // These all print the same thing:
    std::cout << sizeof(a);
    std::cout << sizeof(b);
    std::cout << sizeof(A);
    // These are different:
    std::cout << a.size();  // Prints 1
    std::cout << b.size();  // Prints 100
}

如果你想知道你的向量总共占用了多少空间,你需要自己计算。

你想要n.next.size()

sizeof完全是一个编译时操作,因为它只是查看类型来计算存储它的一个实例需要多少字节。sizeof(n.next)告诉您保存n.next需要多少字节。因为它是一个vector,它很可能使用3个指针(每个8字节)来实现——一个指向已分配数组的开始,一个指向数据的结束,一个指向已分配数组的结束。

作为标准的矢量实现通常被优化为在其生命周期开始时拥有比必要的空间量更多的空间。简单地说,即使您要求的对象较少,该实现也会在8个对象上为vector规划空间,并且只有在超过这个数量后才开始分配更多的内存。

如果你从不使用这些元素,这会浪费一些内存,但是会消除为你添加的每个元素重新分配内存的性能开销。确切的数量取决于实现,有些可能不会这样做,但这是一个典型的优化。

如果你想测量一个元素占用的空间,你需要更大的量;例如,放入100个物体并检查,然后放入200个物体并检查。对于较小的量,您将看到一个固定的大小,直到达到阈值。