【问题标题】:How to explain the value of sizeof(std::vector<int>)?如何解释 sizeof(std::vector<int>) 的值?
【发布时间】:2017-11-27 09:31:09
【问题描述】:

为了了解std::vector&lt;int&gt;的内存消耗我写了:

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 字节的内存,即使是我自己的实现(note :我很可能不会实现我自己的,这只是好奇)。


更新

我用下面的结构再次测试了它:

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

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

我认识到sizeof(std::allocator&lt;int&gt;) 产生1,但我认为这是编译器处理空结构的方式,并且在将其用作成员时已对其进行了优化。但这似乎是我的编译器的问题。

【问题讨论】:

  • 为什么要解释?您是否深入研究了 &lt;vector&gt; 标头的源代码(以及其中包含的 internal 标头)?你真的在乎吗?你愿意花费数周的时间来了解所有血淋淋的细节吗?在我的 Linux/GCC 系统上,#include &lt;vector&gt; 扩展到了一万多行 C++,我没有花时间阅读所有这些。顺便说一句,您的向量使用的大部分内存都是堆中的一些数据...
  • @BasileStarynkevitch 部分好奇。聚会,因为我必须在内存关键环境中使用std::vector,我想知道“如果我自己实现它,我能做得更好吗?”。我很可能不会自己实现任何东西,所以主要是好奇心。我知道大多数内存都在堆上。问题是我似乎有 很多 向量,其中大部分都是空的。所以空内存消耗是这里的重要数字。
  • 您的问题似乎根本与vector 无关。它几乎可以概括为“在 64 位系统上,为什么struct {void *_1; void *_2; void *_3; }; 占用 32 个字节而不是 24 个字节?”。如果这些确实是您所说的结构中的唯一成员。
  • 顺便说一句,在我的 Linux/GCC/x86-64/Debian/Sid sizeof(std::vector&lt;int&gt;) 上是 24。所以你可以考虑改变你的编译器!
  • @BasileStarynkevitch:正如我所说,我并不是说要实现 STL 中存在的所有 vector 功能。但是它的特定子集可以很容易地实现,并且适合需求。特别是在所描述的情况下,空vector 的内存大小很重要 - 这是要走的路。

标签: c++ vector stl sizeof stdvector


【解决方案1】:

编译器无法优化掉一个空成员。这是标准明确禁止的。

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

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

【讨论】:

    【解决方案2】:

    std::vector 的数据成员没有任何标准化,因此您可以假设它是定义的实现。

    您提到了三个指针,因此您可以使用三个指针作为其数据成员来检查类(或结构)的大小。

    我试过运行这个:

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

    Wandbox,得到:

    24 24

    这几乎意味着额外的 8 个字节来自“为满足对齐约束而添加的填充”。

    【讨论】:

    • 谢谢。所以它似乎是我的编译器、实现、操作系统的神器……!?!但似乎可以用 24 个字节来完成。
    • 我会尝试另一个编译器@M.Winter。 如果我很好奇! ;)
    【解决方案3】:

    我最近遇到了同样的问题。虽然我仍然不知道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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-19
      • 1970-01-01
      • 2020-01-26
      • 2017-02-01
      • 1970-01-01
      • 2016-01-06
      • 2017-04-16
      相关资源
      最近更新 更多