C++类空类大小 1 字节

发布于 2025-01-02 14:25:31 字数 138 浏览 2 评论 0原文

我是 C++ 新手,发现了 C++ 的一个特殊功能。我看到空的大小是 1 个字节,我做了一些研究,发现这样做是因为每个对象都必须有一个不同的地址。但我想知道放置的那1个字节的内容是什么。我知道它不包含“this”指针,但它是一个虚拟字节还是实际上有一些内容???

I am new to C++ and a found a peculiar feature in C++. I saw the size of an empty is 1 byte, I did some research and found out that is is done because every object must have a distinct address. But I want to know what is the content of that 1 byte that is placed. I know it does not hold the "this" pointer but is it a dummy byte or is there actually some content???

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

用心笑 2025-01-09 14:25:31

没有内容啊这只是一个虚拟字节。

每个classstructsizeof必须大于0,因此你的行为。这是标准所期望和强制的。

There's no content. It's just a dummy byte.

Every class or struct must have its sizeof greater than 0, ergo your behavior. It's expected and mandated by the standard.

鲜肉鲜肉永远不皱 2025-01-09 14:25:31

标准强制要求同一类型的不同对象应具有不同的地址。这反过来又确保对于任何对象 TT* 充当该对象(对于该类型)的明确标识符。

诚然,您通常不需要知道两个对象是否真的相同,但有时(考虑到 C++ 低级访问)这要么是必要的,要么只是很方便。

因此指定任何对象都不应具有空大小。

不过,此规则有一个例外:当使用空类作为基类时,编译器可能会在某些情况下选择应用空基优化 (EBO),例如:

struct Empty {};

struct Slim: Empty {
  int a;
};

static_assert(sizeof(Slim) == sizeof(int), "");

一般情况下会添加基类的大小,但在这种特殊情况下则没有必要。然而,同一类型的两个不同对象永远不应该具有相同地址的规则仍然适用,因此:

struct Fat: Empty {
  Empty e;
};

static_assert(sizeof(Fat) > sizeof(Empty), "");

EBO 是在模板情况下使用private 继承的主要原因。例如:

template <typename Allocator>
class MyClass: private Allocator {
};

这样,如果发现Allocator是一个空类,则不会有任何开销。一般来说,它经常用于策略,例如传递给map的谓词。

It is mandated by the Standard that different objects of the same type should have different addresses. This in turn ensure that for any object T, T* acts as a unambiguous identifier of this object (for this type).

Granted, you don't often need to know if two objects really are the same or not, but sometimes (given C++ low-level access) this is either necessary or just plain convenient.

It is thus specified that no object should have a null size.

There is an exception to this rule though: when using an empty class as a base class, the compiler may choose to apply the Empty Base Optimization (EBO) is some circumstances, for example:

struct Empty {};

struct Slim: Empty {
  int a;
};

static_assert(sizeof(Slim) == sizeof(int), "");

In general the size of the base class is added, but in this particular case it is not necessary. However the rule that two different objects of the same type should never have the same address still apply, and so:

struct Fat: Empty {
  Empty e;
};

static_assert(sizeof(Fat) > sizeof(Empty), "");

EBO is the main reason for using private inheritance in template situations. For example:

template <typename Allocator>
class MyClass: private Allocator {
};

This way, if it turns out that Allocator is an empty class, there won't be any overhead. In general, it is thus often used for policies, for example the predicates you pass to map.

甜中书 2025-01-09 14:25:31

该字节不包含任何内容,它的存在是为了使某些其他行为变得更好。
例如,考虑另一个类中包含空类的情况。

class Empty
{ };

class TwoEmpties
{
  Empty a;
  Empty b;
};

您可能希望两个成员 &TwoEmpties::a&TwoEmpties::b 的地址不同。为了实现这一点,它们的尺寸必须大于 1。 1.(或者编译器必须在它们之间添加填充,这反过来又会使编译器何时何地向类添加填充的规则变得复杂。)

The byte contains nothing, it is there to make certain other behaviors nicer.
For example consider the case of empty classes contained in another.

class Empty
{ };

class TwoEmpties
{
  Empty a;
  Empty b;
};

You may want the addresses of the two members, &TwoEmpties::a and &TwoEmpties::b, to be different. For this to happen they must have size > 1. (or the compiler would have to add padding between them, which would in turn complicate the rules for when and where the compiler can add padding to classes.)

明月夜 2025-01-09 14:25:31

您可以使用调试器或类似 printf("%x", *(unsigned char *)&myobj); 之类的简单工具来查看字节的内容。我还没有阅读 C++ 规范,但我猜测字节的内容未定义,因此行为取决于编译器和您的操作系统。

You can use your debugger or something simple like printf("%x", *(unsigned char *)&myobj); to see the contents of the byte. I haven't read the C++ specification but I would guess that the contents of the byte are undefined so the behavior depends on the compiler and your OS.

怀里藏娇 2025-01-09 14:25:31

空类的大小为 1,因为当创建该类的对象时,如果大小=0,它们将存储在内存中的同一位置。

假设当您创建一个对象时,地址为 1000

如果类的大小为 0,则对象的大小也必须为 0。

(therefore, object is located at 1000+0=1000)

因此,现在如果创建了另一个对象,

Add. of 2nd object=1000+0th location

两个对象都具有相同的地址,这是未定义的行为,不应发生,因为引用哪个对象会存在歧义。

因此,空类被赋予一个字节的内存以防止这种情况发生。

An empty class has a sizeof 1 because when objects of that class are created they will be stored on the same location in memory if size=0.

Suppose that when you create an object the address is 1000.

If size of the class is 0 hence the size of the object must be 0 as well.

(therefore, object is located at 1000+0=1000)

So now if another object is made,

Add. of 2nd object=1000+0th location

Both the objects have same address and this is undefined behavior and shouldn't occur as there will be ambiguity to which object is being referred to.

Hence empty classes are given a byte of memory to prevent such situations from happening.

茶底世界 2025-01-09 14:25:31

这是一个虚拟字节 - 构造函数和析构函数将很简单,没有“存储数据”。

That's a dummy byte - constructor and destructor will be trivial, there's no "data stored".

携君以终年 2025-01-09 14:25:31

我遇到了类似的问题,似乎可以用一点技巧来定义一个长度为零的类。我不知道这是否只是因为g++,但请看下面的代码片段:

struct ONE {};
struct ZERO { char x[0]; };

int main() {
  cout << sizeof(ONE) << ", " << sizeof(ZERO) << endl;

  ONE* po1 = new ONE;
  ONE* po2 = new ONE;
  cout << po1 << ", " << po2 << endl;

  ZERO* pz1 = new ZERO;
  ZERO* pz2 = new ZERO;
  cout << pz1 << ", " << pz2 << endl;
}

输出是:

1, 0
0xe4f010, 0xe4f030
0xe4f050, 0xe4f070

所以空类的大小是1(根据C++标准),但如果它只有一个零长度的数组字段大小变为零。如果使用 new 在堆上分配了一个新的大小为零的类,则返回有效地址,如果分配多次,它们的指针将指向不同的内存地址。

I faced to similar problem and it seems that one can define a class with zero length with a little trick. I do not know if it is just because of g++, but see the following code snippet:

struct ONE {};
struct ZERO { char x[0]; };

int main() {
  cout << sizeof(ONE) << ", " << sizeof(ZERO) << endl;

  ONE* po1 = new ONE;
  ONE* po2 = new ONE;
  cout << po1 << ", " << po2 << endl;

  ZERO* pz1 = new ZERO;
  ZERO* pz2 = new ZERO;
  cout << pz1 << ", " << pz2 << endl;
}

The output is:

1, 0
0xe4f010, 0xe4f030
0xe4f050, 0xe4f070

So the size of an empty class is one (according to the C++ standard), but if it has just a zero length array field the size become zero. If a new really zero sized class is allocated on the heap with new a valid address is returned and if allocated multiple times their pointers are pointing to different memory addresses.

放肆 2025-01-09 14:25:31

据我所知,上述所有答案都不正确。
正确答案是默认情况下,创建类对象时会调用 4 个内置函数,即

  1. 默认构造函数

  2. 默认析构函数

  3. 函数

    复制构造函数

  4. 重载赋值运算符

因此空类的大小为 1byte ,
示例:试试这个

#include<iostream>
using namespace std;
class Test
{
};
int main()
{
Test t;
cout<< "size of empty class is "<<sizeof(t);
}

All the above answer is not right as per my knowledge .
The correct answer is by default 4 inbuilt functions are called when object of class is created that is

  1. Default constructor

  2. Default destructor

  3. Copy constructor

  4. overloaded assignments operator

hence the size of empty class is 1byte ,
Example : try this

#include<iostream>
using namespace std;
class Test
{
};
int main()
{
Test t;
cout<< "size of empty class is "<<sizeof(t);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文