PAYATHON 2026

为什么 C++ 中 sizeof(std::vector<int>) 的结果是 24?

数据阿明

结论

sizeof(v) 测量的是 std::vector<int> 对象本身占用的字节数,不包含它管理的动态元素存储。你看到的 24 字节与一种常见布局相符:对象中有三个指针,每个指针占 8 字节。不过,单凭这个结果无法确定对象的内部结构。

参考资料中的 Public Types 列出的是公开类型别名,不会在每个 vector 对象中分别占用存储空间。C++ 标准也没有规定 std::vector<int> 必须占 24 字节。

typedef 声明不会创建数据成员

下面两种声明的含义不同:

struct Example {
    typedef int value_type; // 声明类型别名
    int value;             // 声明非静态数据成员
};

value_type 只是类型的名称;value 是对象需要存储的数据成员。

同样,std::vector<int>::value_type 表示 int,size_type 表示用于大小和数量的类型,iterator 表示迭代器类型。这些名称不意味着每个 vector 对象都保存了相应类型的变量。

例如,typedef size_t size_type 本身不能证明 vector 内部有一个 size_t 数据成员。

24 字节通常从哪里来?

对于普通的 std::vector<int>,常见的 libstdc++ 实现使用三个指针记录元素存储区的边界。下面是一个示意结构:

struct VectorStorageIllustration {
    int* begin;
    int* end;
    int* capacity_end;
};

这只是布局示意,不是标准规定的 std::vector 定义。三个指针分别表示:

  • begin:元素存储区的起点。
  • end:已构造元素区间的终点。
  • capacity_end:已分配存储区的终点。

对于已经分配存储区的情况,可以通过指针差计算元素数量和容量,不必另外保存元素计数成员。

如果指针大小为 8 字节,且分配器等实现细节没有增加额外空间,这种布局可能占用 24 字节:

3 × 8 = 24 字节

默认分配器通常不需要保存状态,实现可以通过空基类优化等机制避免额外占用空间。因此,搜索结果中的“两个指针和一个 size_t”不能直接当作当前实现的布局说明。

如何检查当前环境?

可以先观察指针大小、对象大小和元素数量:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v;

    std::cout << "sizeof(int*) = " << sizeof(int*) << '\n';
    std::cout << "sizeof(v) = " << sizeof(v) << '\n';
    std::cout << "size = " << v.size() << '\n';
    std::cout << "capacity = " << v.capacity() << '\n';

    v.push_back(42);

    std::cout << "sizeof(v) after push_back = "
              << sizeof(v) << '\n';
    std::cout << "size after push_back = " << v.size() << '\n';
}

push_back 会改变元素数量,也可能触发动态内存分配,但不会改变同一类型对象的 sizeof。

要确认这 24 字节具体由哪些成员组成,需要查看当前编译环境实际使用的标准库头文件,或者用调试器检查类型布局。单独测量 sizeof 无法证明内部成员是什么。

需要注意什么?

sizeof(v) 不等于容器使用的全部内存。动态元素存储、内存分配器的管理开销等,都不包含在这个数值里。

不同标准库、目标平台、调试配置和分配器类型都可能影响对象大小。24 字节是当前环境下的观察结果,不能作为跨平台代码中的固定假设。

备注:内容仅供参考。