C++ 类对象的总内存 [英] total memory of a C++ class object

查看:25
本文介绍了C++ 类对象的总内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么下面这段代码给出了 24 作为答案?即后面的类X的对象总大小是多少,24个字节?我使用的是 64 位机器.

#include 使用命名空间标准;X级{矢量 <bool>F;国际b;民众:X(){f.push_back(true);}};int main(){X ob;cout<

解决方案

也就是下面X类的对象总大小是多少,24字节?我使用的是 64 位机器.

C++ 几乎不保证类型大小,也不保证标准容器的内存布局.因此,对于此类问题,说明您的编译器和调用它的选项也很重要.

<块引用>

class X{矢量 <bool>F;国际b;民众:X(){f.push_back(true);}};

您可以查看 sizeof(int)sizeof(vector) 的单独结果.他们可能会透露以下信息:

  • int b 的 8 个字节.
  • 16 个字节用于 vectorf.

vector 的 16 个字节更难分析.一些东西可以存储在对象中,例如:

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

如果您想确定,您可以查看您的实现的头文件,以了解您的编译器如何在内存中布置 std::vector.

请注意,std::vector 的内存布局可能与所有其他 std::vector 不同,因为

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

std::vector 不需要那种特殊处理,这就解释了为什么它更小.

由于空基优化.

<小时>

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

回到你最初的问题,最重要的一点是你的编译器可以以任何它想要的方式布置 std::vector 只要它对根据 C++ 标准的外部世界.它也可以选择根本不优化 std::vector.如果不了解有关您的编译器的更多信息,我们无法告诉您更多信息.它在 64 位机器上运行的信息是不够的.

<小时>

[*] std::vector 应该是一种节省空间的优化,但显然在这个实现中这只与空间有关被动态分配的元素占用,而不是向量本身的静态大小.

Why does the following piece of code gives 24 as an answer? That is, how is the total size of the object of following class X, 24 bytes? I'm using 64-bit machine.

#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;
}

解决方案

That is, how is the total size of the object of following class X, 24 bytes? I'm using 64-bit machine.

C++ makes few guarantees about type sizes and none about the memory layout of standard containers. For questions like this, it is therefore also important to state your compiler and the options with which you invoke it.

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

You can look at the individual results for sizeof(int) and sizeof(vector<bool>). They will probably reveal the following:

  • 8 bytes for int b.
  • 16 bytes for vector<bool> f.

The 16 bytes for vector<bool> are harder to analyse. Several things could be stored in the object, for example:

  • An instance of the std::allocator<bool> that you "invisibly" pass via a default argument when you construct the vector.
  • A pointer to the start of the dynamically allocated memory occupied by the data to represent the vector's bool elements.
  • A pointer to the end of that memory (for constant-time capacity() calls).
  • A pointer to the last element inside that dynamically allocated memory (for constant-time size() calls).
  • The current element count or the current capacity count (for constant-time size and capacity() calls).

If you want to know for sure, you can probably look into your implementation's header files to see how your compiler lays out std::vector<bool> in memory.

Note that the memory layout for a std::vector<bool> can be different from all other std::vectors due to special optimisations. For example, on my machine with MSVC 2013, compiled simply with cl /EHsc /Za /W4 stackoverflow.cpp, sizeof(std::vector<bool>) is 16 whereas sizeof(std::vector<int>) is 12 [*].

Since header files internal to the implementation can be quite hard to read, an alternative way is to run your program in a debugger and inspect the object there. Here's an example screenshot from Visual Studio Express 2013:

As you can see, the sizeof(std::vector<bool>) here comes from three times sizeof(unsigned int*) for pointers to first element, last element and capacity end in the dynamically allocated memory, plus one extra sizeof(unsigned int) for the element count, which is necessary due to the aforementioned special optimisation for std::vector<bool>, which means that calculating the difference between the pointers to first and last element may not necessarily reveal the number of elements that the vector represents to outside code.

std::vector<int> does not need that special handling, which explains why it's smaller.

The inherited std::_Container_base0 is apparently not taken into account due to Empty base optimization.


All things considered, this is all quite complicated stuff. But such is the world of standard-library implementors! Remember that all things you see inside of header files are strictly internal. You cannot, for example, suppose the existence of std::_Container_base0 in your own code in any way. Pretend that it does not exist.

Coming back to your original question, the most important point is that your compiler may lay out a std::vector<bool> in any way it wants to as long as it behaves correctly to the outside world according to the C++ standard. It may also choose not to optimise std::vector<bool> at all. We cannot tell you much more without knowing more about your compiler. The information that it runs on a 64-bit machine is not enough.


[*] std::vector<bool> is supposed to be a space-efficient optimisation, but apparently in this implementation this only relates to space occupied by the dynamically allocated elements, not the static size of the vector itself.

这篇关于C++ 类对象的总内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆