没有数据成员的类的大小返回为 1 个字节,即使声明了隐式“this”指针。返回的大小不应该是 4 个字节(在 32 位机器上)吗?我遇到了一些文章,指出“this”指针不计入计算对象的大小。但我无法理解其原因。此外,如果任何成员函数被声明为虚拟,则类的大小现在返回为 4 个字节。这意味着 vptr 被计算用于计算对象的大小。为什么要考虑 vptr 而忽略“this”指针来计算对象的大小?
4 回答
this
指针不是类的成员。它只是一个在属于该类的方法中用于引用当前实例的构造。
如果你有这样的课程:
class IntPair
{
public:
IntPair(int a, int b) : _a(a), _b(b) { }
int sum() const { return _a + _b; }
public:
int _a;
int _b;
};
这个类只需要int
每个实例的两个实例的空间。一旦您创建了一个实例并运行该sum()
方法,就会使用指向该实例的指针调用该方法,但该指针始终来自其他地方,它不存储在对象实例中。
例如:
IntPair *fib12 = new IntPair(89, 144);
cout << fib12->sum();
注意成为this
指针的变量是如何存储在对象之外的,在创建它的范围内。
实际上,您可以始终将上述方法转换为:
static int sum2(const IntPair* instance)
{
return instance->_a + instance->_b;
}
如果上述内容是在类中定义的(因此它可以访问私有成员),则没有区别。事实上,这就是方法在幕后实现的方式;this
指针只是所有成员方法的隐藏参数。
调用将变为:
IntPair* fib12 = new IntPair(89, 144);
cout << IntPair::sum2(fib12);
“this”不作为数据成员存储在类中,它只是指向类实例的“指针”。将其视为传递给该方法的“隐藏参数”。事实上,在 Win32 系统上,它通常在 ecx 寄存器中传递(不是我最初认为的 eax)。
只要您有 1 个或多个虚拟方法,您的应用程序就需要一种方法来存储指向虚拟方法的指针。这称为 vtable,它对于同一类的所有实例都是相同的。由于您需要在运行时知道要调用哪个“虚拟方法”的“显式”方法,因此指向 vtable 的指针存储在类实例中。因此 vtable-pointer(或 vptr)需要 4 个字节(或 64 位系统上的 8 个字节)。
this 指针不存储在对象内部。没有必要这样做。您已经有一个指针或对象来调用函数。至于 1 的大小,C++ 标准要求 distict 对象具有不同的地址。
指针的大小始终是需要存储在内存中的指针类型的大小。
例如,如果 int 的内存地址在 64 位架构上是 32 位,则
整数a = 10;int * b = &a; 大小(乙);//32 sizeof(&b); 64