【发布时间】:2013-10-29 20:24:41
【问题描述】:
我习惯了 C 的固定大小的结构。 不知道 C++ 对象是否是固定的。我的意思是总是可以预测对象的大小吗?在编译期间?和/或运行时间?还是不可能,除非使用 sizeof 运算符? 我知道它依赖于硬件平台。除此之外,还有什么?
【问题讨论】:
-
对象的布局取决于平台特定的 ABI。一个例子是refspecs.linuxbase.org/cxxabi-1.83.html。
我习惯了 C 的固定大小的结构。 不知道 C++ 对象是否是固定的。我的意思是总是可以预测对象的大小吗?在编译期间?和/或运行时间?还是不可能,除非使用 sizeof 运算符? 我知道它依赖于硬件平台。除此之外,还有什么?
【问题讨论】:
当然,C++ 对象具有固定大小。如果它不是固定的,并且你创建了一个对象数组,编译器如何知道要分配多少空间?
适用于结构的相同规则适用于此处,每种数据大小的总和加上对齐的任何填充,如果您使用任何虚拟函数,则 V 表指针会额外增加 4 或 8 个字节,具体取决于你的机器。
【讨论】:
new int[x] 是反例。数组是单个对象,甚至像这样的可变长度数组。 “编译器如何知道为这些数组分配多少空间?”不是反驳:没有变长数组的数组。
s correct. If new int[x]` 显然你需要一个指向堆上动态分配的整数的指针。此指针大小将根据架构略有不同。当然,这个分配的数据与实际的类或结构大小是分开的。所以class Foo { int someInt; int* someInts; } 如果在 32 位系统上,int 的大小也是 4 个字节,则将始终为 8 个字节。如果在构造函数中,您有 someints = new int[6400] 并在此 Foo 实例上调用了 sizeof(),它仍然是 8 个字节。
对象本身的大小可以通过调用sizeof 来检索,并且在编译时是已知的。但是该对象可以管理其他一些资源,并且没有直接的方法可以知道该资源占用了多少内存。
例如,gcc 32bits,sizeof(std::vector<T>) 是 12(3 个指针),但它可能管理数百万个 T 实例,这些实例本身可能很大。
【讨论】:
std::stringstd::map等容器都在堆上存储数据,所以它们的大小是固定的。
即使使用 C,您也受到填充、对齐等的摆布。话虽如此,如果您知道成员变量的大小,C++ 中 struct/class 的大小通常是可以预测的。这变得有点模糊的唯一一次是当您开始介绍virtual functions 和virtual inheritance 时。在这种情况下,编译器需要存储一些额外的簿记信息。无论如何,每个对象的大小在编译时是已知的,因此sizeof 运算符是一个编译时特性(这解释了为什么它可以用于模板元编程。)
C++ 遵循“不为不使用的东西付费”的原则。如果您所做的只是将相似的数据和函数组合到一个类中,那么您的对象的行为将与它们是具有全局函数的 C 中的结构一样。如果您需要更高级的功能,则按使用次数付费。
【讨论】:
任何类型都有一个众所周知的大小,点。 (动态内存分配不考虑)
仅使用类型的前向声明的声明是无效的:
class Unknown;
class Failure {
Unknown x;
};
使用指针使声明有效:
class Unknown;
class Success {
Unknown *x;
};
实际上 C 和 C++ 没有区别。两者都需要一个众所周知的大小。
【讨论】:
是与否! class 或 struct 可以从堆中为其内部数据分配任意大小。不过,管理这个的成员将设置一个固定大小的结构。
【讨论】: