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

C++;类空类大小为1字节 我是C++的新手,在C++中发现了一个特殊的特性。我看到一个空的大小是1字节,我做了一些研究,发现这样做是因为每个对象都必须有一个不同的地址。但是我想知道放置的1字节的内容是什么。我知道它不包含“this”指针,但它是一个伪字节还是实际上有一些内容,c++,sizeof,C++,Sizeof,没有内容。这只是一个伪字节 每个类或结构的大小必须大于0,以符合您的行为。这是标准所期望和要求的。这是一个伪字节-构造函数和析构函数将是微不足道的,没有“存储的数据”。您可以使用调试器或类似于printf(“%x”、*(unsigned char*)&myobj)的简单工具以查看字节的内容。我没有读过C++规范,但是我想猜测->强>字节的内容是未定义的,所以行为取决于编译器和你的操作系统。< /P> < P>字节不包含任何内容,它是为了使某些其他行为更好。 例如,考虑另一个包含空类的情况。 cl

没有内容。这只是一个伪字节


每个
结构
大小必须大于
0
,以符合您的行为。这是标准所期望和要求的。

这是一个伪字节-构造函数和析构函数将是微不足道的,没有“存储的数据”。

您可以使用调试器或类似于
printf(“%x”、*(unsigned char*)&myobj)的简单工具
以查看字节的内容。我没有读过C++规范,但是我想<强>猜测->强>字节的内容是未定义的,所以行为取决于编译器和你的操作系统。< /P> < P>字节不包含任何内容,它是为了使某些其他行为更好。 例如,考虑另一个包含空类的情况。

class Empty
{ };

class TwoEmpties
{
  Empty a;
  Empty b;
};

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

标准规定相同类型的不同对象应具有不同的地址。这进而确保对于任何对象
T
T*
充当此对象(此类型)的明确标识符

当然,您并不需要知道两个对象是否真的相同,但有时(给定C++低级访问)这是必要的或只是简单的。 因此,指定任何对象的大小都不应为空

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

struct Empty {};

struct Slim: Empty {
  int a;
};

static_assert(sizeof(Slim) == sizeof(int), "");
template <typename Allocator>
class MyClass: private Allocator {
};
通常会添加基类的大小,但在这种特殊情况下不需要添加。但是,相同类型的两个不同对象不应具有相同地址的规则仍然适用,因此:

struct Fat: Empty {
  Empty e;
};

static_assert(sizeof(Fat) > sizeof(Empty), "");
EBO是在模板情况下使用
private
继承的主要原因。例如:

struct Empty {};

struct Slim: Empty {
  int a;
};

static_assert(sizeof(Slim) == sizeof(int), "");
template <typename Allocator>
class MyClass: private Allocator {
};
模板
类MyClass:专用分配器{
};

这样,如果
分配器
是一个空类,就不会有任何开销。一般来说,它通常用于策略,例如,传递给
map

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

假设创建对象时
地址为1000

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

(therefore, object is located at 1000+0=1000)
所以现在如果制造了另一个物体

Add. of 2nd object=1000+0th location
这两个对象都有相同的地址,这是未定义的行为,不应该发生,因为引用的对象不明确


因此,
为空类提供了一个字节的内存
,以防止此类情况发生。

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

  • 默认构造函数

  • 默认析构函数

  • 复制构造函数

  • 重载赋值运算符

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

    #include<iostream>
    using namespace std;
    class Test
    {
    };
    int main()
    {
    Test t;
    cout<< "size of empty class is "<<sizeof(t);
    }
    
    #包括
    使用名称空间std;
    课堂测试
    {
    };
    int main()
    {
    试验t;
    
    cout我也遇到过类似的问题,似乎可以用一个小技巧定义一个长度为零的类。我不知道这是否仅仅是因为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;
    }
    

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

    无可否认,您通常不需要这两个成员的地址e大多数情况下,您并不关心两个成员的地址。这条规则只适用于少数用例,尽管它们被认为足够重要,可以强制执行。@MatthieuM.同意。在g++中稍微修正了措辞,可以定义一个大小为0的类。请看我的答案。静态零长度数组的形式不好ed.@Deduplicator也许你是对的,但我已经见过这样的结构(最后一项是char[0])好几次了。所以它以某种方式传播开来。struct{int length;char d[0];};是可变记录长度的技巧(尽管我不喜欢称任何如此强大的东西为“技巧”)。struct{int length;åchar d[0];};是可变记录长度技巧(尽管我不喜欢将任何如此强大的东西称为“技巧”:)。作为旁注:我在继承链中使用std::Is_pod()的空结构。添加空成员(char d[0])违反继承空类的类的Is pod测试。例如:struct a{static void fn();};结构B:A{int B;};只要结构A中没有定义成员,结构B将传递std::is_pod()。