如何解释sizeof(std :: vector <int>)的值?

时间:2017-11-27 09:31:10

标签: c++ vector stl sizeof stdvector

为了理解我写的std::vector<int>的内存消耗:

std::cout << sizeof(std::vector<int>) << std::endl;

这会产生32。我试图了解这个价值来自哪里。有些人在源代码中看到std::vector存储了指针_MyFirst_MyLast_MyEnd,它们解释了24字节的内存消耗(在我的64位系统上)。

最后8字节怎么样?据我所知,存储的分配器不使用任何内存。这也许是实现定义的(是吗?),所以这可能有所帮助:我正在使用MSVC 2017.5。我不保证通过查看代码找到所有成员;代码看起来很混乱。

似乎一切都很顺利,但答案可能如下:?Why isn't sizeof for a struct equal to the sum of sizeof of each member?。但我用简单的struct Test { int *a, *b, *c; };测试了它,它满足sizeof(Test) == 24

一些背景

在我的程序中,我将有很多的向量,似乎大多数都是空的。这意味着循环内存消耗来自空状态,即堆分配的内存不是那么重要。

一个简单的“只为这个用例”-vector很快实现了,所以我想知道我是否遗漏了任何东西,无论如何我都需要32字节的内存,即使是我自己的实现(注意 :我很可能没有实现我自己的,这只是好奇心。)

更新

我使用以下结构再次测试它:

struct Test
{
    int *a, *b, *c;
    std::allocator<int> alloc;
};

现在给了sizeof(Test) == 32。似乎即使std::allocator没有内存消耗成员(我认为),它的存在会将Test的大小提高到32字节。

我认识到sizeof(std::allocator<int>)会产生1,但我认为这是编译器处理空结构的方式,并且当它被用作成员时会被优化掉。但这似乎是我编译器的一个问题。

2 个答案:

答案 0 :(得分:2)

编译器无法优化掉空成员。标准明确禁止它。

  

空类类型的完整对象和成员子对象应具有非零大小

另一方面,空基类子对象的大小可能为零。这正是GCC / libstdc ++如何应对这个问题:它使向量实现继承了分配器。

答案 1 :(得分:1)

我最近遇到了同样的问题。虽然我仍然不明白 std::vector 是如何进行这种优化的,但我找到了一种通过 C++20 的方法。

C++ attribute: no_unique_address (since C++20)

struct Empty {};
struct NonEmpty {
    int* p;
};

template<typename MayEmpty>
struct Test {
    int* a;
    [[no_unique_address]] MayEmpty mayEmpty;
};

static_assert(sizeof(Empty) == 1);
static_assert(sizeof(NonEmpty) == 8);

static_assert(sizeof(Test<Empty>) == 8);
static_assert(sizeof(Test<NonEmpty>) == 16);