我是C ++的新手,在C ++中发现了一个特殊的功能。我看到一个空的大小是1个字节,我做了一些研究,发现这是完成的,因为每个对象必须有一个不同的地址。但是我想知道放置的那个1字节的内容是什么。我知道它不会持有“this”指针,但它是一个虚拟字节还是实际上有一些内容?
答案 0 :(得分:11)
没有内容。它只是一个虚拟字节。
每个class
或struct
必须使其sizeof
大于0
,这样才能行事。它是标准的预期和强制要求。
答案 1 :(得分:8)
标准强制要求相同类型的不同对象具有不同的地址。这反过来确保对于任何对象T
,T*
充当此对象的明确标识符(对于此类型)。
当然,您通常不需要知道两个对象是否真的相同,但有时(给定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
的谓词。
答案 2 :(得分:3)
该字节不包含任何东西,它可以使某些其他行为更好。 例如,考虑另一个包含空类的情况。
class Empty
{ };
class TwoEmpties
{
Empty a;
Empty b;
};
您可能希望两个成员&TwoEmpties::a
和&TwoEmpties::b
的地址不同。要做到这一点,他们的大小必须> 1.(或者编译器必须在它们之间添加填充,这反过来会使编译器在何时何地向类添加填充的规则变得复杂。)
答案 3 :(得分:2)
您可以使用调试器或类似printf("%x", *(unsigned char *)&myobj);
的简单内容来查看字节的内容。我还没有读过C ++规范,但我会猜测字节的内容是未定义的,所以行为取决于编译器和你的操作系统。
答案 4 :(得分:1)
empty class has a sizeof 1
因为当创建该类的对象时,如果size = 0,它们将存储在内存中的相同位置。
假设您在创建对象时address is 1000
。
如果class is 0
的大小也是object must be 0
的大小。
(therefore, object is located at 1000+0=1000)
现在如果有另一个对象,
Add. of 2nd object=1000+0th location
两个对象都具有相同的地址,这是未定义的行为,不应该出现,因为对象被引用会有歧义。
因此empty classes are given a byte of memory
可以防止这种情况发生。
答案 5 :(得分:0)
这是一个虚拟字节 - 构造函数和析构函数将是微不足道的,没有“数据存储”。
答案 6 :(得分:0)
根据我的知识,以上所有答案都是不对的。 默认情况下,正确的答案是在创建类的对象
时调用4个内置函数默认构造函数
默认析构函数
复制构造函数
重载分配运算符
因此空类的大小是1byte, 示例:试试这个
#include<iostream>
using namespace std;
class Test
{
};
int main()
{
Test t;
cout<< "size of empty class is "<<sizeof(t);
}
答案 7 :(得分:0)
我面临类似的问题,似乎可以用一个小技巧定义一个零长度的类。我不知道是不是因为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
所以空类的大小是一(根据C ++标准),但如果它只有一个零长度数组字段,则大小变为零。如果在具有new
的堆上分配了一个新的真正零大小的类,则返回一个有效地址,如果多次分配它们的指针指向不同的内存地址。