C++对象是否有固定的大小?

3

我曾经使用C语言的固定结构体大小。不知道C++对象的大小是否固定。我的意思是对象的大小是否总是可以在编译时预测到?或者在运行时?还是只有使用sizeof操作符才能得知大小?我知道它取决于硬件平台,除此之外还有什么因素影响大小呢?


对象的布局取决于ABI,它是特定于平台的。一个例子是http://refspecs.linuxbase.org/cxxabi-1.83.html。 - Alan Stokes
5个回答

4

对象本身的大小可以通过调用sizeof来获取,这在编译时是已知的。但是该对象可能管理其他资源,而无法直接知道该资源占用多少内存。

例如,在gcc 32位中,sizeof(std::vector<T>)为12(3个指针),但它可能管理着数百万个可能很大的T实例。


容器,例如std::stringstd::map,都将数据存储在堆上,因此它们的大小是固定的。 - heLomaN

4

当然,C++对象有固定的大小。如果大小不确定,并且您制作了一个对象数组,编译器如何知道要分配多少空间?

这里适用于结构体的相同规则,每种数据类型的大小总和加上任何填充以对齐,如果使用任何虚拟函数,则需要额外4或8字节的V表指针,具体取决于计算机的架构。


如果这是完全正确的,那么这正是我想要的。还有其他人可以确认吗? - Tim
这是错误的。new int[x] 是反例。数组是单个对象,即使是像这样的可变长度数组也是如此。“编译器如何知道为这些数组分配多少空间?”不是反驳:没有可变长度数组的数组。 - MSalters
2
没错。如果使用new int[x],那么显然需要一个指向堆上动态分配的整数的指针。这个指针的大小将根据架构略有不同。当然,这个分配的数据与实际类或结构体的大小是分开的。所以 class Foo { int someInt; int* someInts; } 如果在32位系统上,int也是4字节大小,那么它总是8字节。如果在构造函数中,你有someints = new int[6400]并且调用了Foosizeof(),它仍然是8字节。 - Lloyd Crawley

2
任何类型都有一个众所周知的大小——点。(动态内存分配不计算在内)
仅使用类型的前向声明进行声明是无效的:
class Unknown;
class Failure {
   Unknown x;
};

使用指针可以使声明有效:
class Unknown;
class Success {
   Unknown *x;
};

实际上,C和C++并没有区别。两者都需要一个已知的大小。


2
即使使用 C 语言,你仍然需要考虑填充、对齐等问题。尽管如此,在 C++ 中,如果你知道成员变量的大小,则可以通常预测出一个结构体/类的大小。唯一让人有些困惑的情况是当你开始引入虚函数和虚继承时。在这种情况下,编译器需要存储一些额外的记录信息。无论如何,每个对象的大小都在编译时已知,因此 sizeof 运算符是一个编译时特性(这也解释了为什么它可用于模板元程序设计)。
C++ 遵循“不付出你不使用的代价”的原则。如果你只是将类似数据和函数组合到一个类中,那么你的对象与在 C 中使用结构体和全局函数的对象行为相同。如果你需要更高级的功能,则需要按照使用情况进行付费。

您的意思是每个虚函数使用都会创建一个以上的项,这些项可能具有指针和其他系统/应用程序变量/指针吗?这是否意味着在使用虚函数后,您使用sizeof运算符将看到差异? 那么在此对象内部的另一个对象呢? 函数的大小是多少?函数指针的大小是多少? - Tim
1
该对象需要存储一个指向函数指针表的指针(称为虚函数表或vtable)。它实际上在结构体中存储这个指针的位置是由具体实现定义的,这可能会影响你对对象布局的任何概念。 - bstamour

1
是和否!classstruct可以从堆中分配其内部数据的任意大小。管理此类数据的成员将设置固定大小的结构。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接