【问题标题】:total memory of a C++ class objectC++ 类对象的总内存
【发布时间】:2015-10-04 08:07:22
【问题描述】:

为什么以下代码给出 24 作为答案?也就是下面X类的对象的总大小是多少,24字节?我使用的是 64 位机器。

#include <bits/stdc++.h>
using namespace std;
class X
{
    vector <bool> f;
    int b;
    public:
    X(){
        f.push_back(true);
        }
};
int main(){
    X ob;
    cout<<sizeof(ob);
    return 0;
}

【问题讨论】:

  • 您期望什么? vector 类也有内部变量来管理它的数据。我不认为标准定义了空向量的大小,所以它取决于实现。
  • @AlexLop.:请注意,向量是否为空与其sizeof 无关。前者是动态的,后者是静态的。

标签: c++ memory memory-management 64-bit


【解决方案1】:

即下面X类的对象总大小如何,24 字节?我使用的是 64 位机器。

C++ 很少保证类型大小,也没有保证标准容器的内存布局。因此,对于此类问题,说明您的编译器以及调用它的选项也很重要。

class X
{
    vector <bool> f;
    int b;
    public:
    X(){
        f.push_back(true);
        }
};

您可以查看sizeof(int)sizeof(vector&lt;bool&gt;) 的单独结果。他们将可能揭示以下内容:

  • int b 为 8 个字节。
  • vector&lt;bool&gt; f 为 16 个字节。

vector&lt;bool&gt; 的 16 个字节更难分析。有几样东西可以存储在对象中,例如:

  • std::allocator&lt;bool&gt; 的一个实例,您在构造向量时通过默认参数“不可见地”传递。
  • 指向数据占用的动态分配内存起点的指针,用于表示向量的bool 元素。
  • 指向该内存末尾的指针(用于恒定时间的capacity() 调用)。
  • 指向动态分配内存中最后一个元素的指针(用于常量时间size() 调用)。
  • 当前元素计数或当前容量计数(用于恒定时间 sizecapacity() 调用)。

如果你想确定,你可以查看你的实现的头文件,看看你的编译器如何在内存中布置std::vector&lt;bool&gt;

请注意,由于special optimisationsstd::vector&lt;bool&gt; 的内存布局可能与所有其他 std::vectors 不同。例如,在我使用 MSVC 2013 的机器上,仅使用 cl /EHsc /Za /W4 stackoverflow.cpp 编译,sizeof(std::vector&lt;bool&gt;) 是 16 而sizeof(std::vector&lt;int&gt;) 是 12 [*]

由于实现内部的头文件可能很难阅读,另一种方法是在调试器中运行程序并检查那里的对象。这是 Visual Studio Express 2013 的示例屏幕截图:

如您所见,这里的sizeof(std::vector&lt;bool&gt;) 来自三倍sizeof(unsigned int*),用于指向动态分配内存中第一个元素、最后一个元素和容量结束的指针,加上一个额外的sizeof(unsigned int) 用于元素计数,即由于上述对std::vector&lt;bool&gt; 的特殊优化,这是必要的,这意味着计算指向第一个元素和最后一个元素的指针之间的差异可能不一定会向外部代码揭示向量表示的元素数量。

std::vector&lt;int&gt; 不需要这种特殊处理,这就解释了为什么它更小。

由于Empty base optimization,显然没有考虑继承的std::_Container_base0


考虑到所有因素,这都是相当复杂的事情。但这就是标准库实现者的世界!请记住,您在头文件中看到的所有内容都是严格内部的。例如,您不能以任何方式假设您自己的代码中存在std::_Container_base0。假装它不存在。

回到你原来的问题,最重要的一点是你的编译器可以以任何它想要的方式布置一个std::vector&lt;bool&gt;,只要它根据 C++ 标准对外部世界表现正确。它也可能选择根本不优化std::vector&lt;bool&gt;。在不了解您的编译器的情况下,我们无法告诉您更多信息。它在 64 位机器上运行的信息是不够的。


[*]std::vector&lt;bool&gt; 应该是一种节省空间的优化,但显然在这个实现中这只涉及动态分配的元素占用的空间,而不是静态大小向量本身。

【讨论】:

    【解决方案2】:

    vector 维护自己的内部变量用于记账和分配器。

    将您机器上int 的大小加到向量的大小上,得到总和。

    注意:

    关于 int,在任何 64 位 C/C++ 编译器上,指针的大小应该是 8 字节,但不一定是 int 的大小。

    您可以在此处查看 vector(for gcc) 的内部结构,以便快速查找: https://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/api/a01115_source.html

    【讨论】:

    • 是什么让你认为 OP 使用 GCC?
    • 是什么让你觉得他没有?反正我已经编辑过了
    • 只是想让 OP 不相信 C++ 对容器类有某种“参考实现”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 2011-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    相关资源
    最近更新 更多