编辑 :所以我发现我还是在这个月获得选票后,即使我原来的答复是坏的和误导性的(我甚至不能记得我当时想,这不会使一个很大的意义!),所以我想我会尝试和澄清的情况下,人们仍然必须通过搜索到达这里。
在最正常的情况下,你几乎可以想到的
struct A {
int i;
int foo() { return i; }
};
A a;
a.foo();
如
struct A {
int i;
};
int A_foo( A* this ) { return this->i; };
A a;
A_foo(&a);
(开始看起来像C
吧?)所以,你会觉得指针&A::foo
也只是同一个正常的函数指针。 但也有一对夫妇的并发症:多重继承和虚拟功能。
所以,想象一下,我们有:
struct A {int a;};
struct B {int b;};
struct C : A, B {int c;};
这可能是布局是这样的:
正如你所看到的,如果你想指向与对象A*
或C*
,你点开始,但如果你想指向其与B*
您必须在中间的某个点。
所以,如果C
继承了一些成员函数B
,你想指向它,然后调用一个函数C*
,它需要知道洗牌this
指针。 这些信息需要存储在某个地方。 因此,它被与函数指针集中英寸
现在对每一个有类virtual
函数,编译器创建它们的列表称为虚拟表 。 然后,它增加了一个额外的指针此表到类(vptr的 )。 因此,对于这个类的结构:
struct A
{
int a;
virtual void foo(){};
};
struct B : A
{
int b;
virtual void foo(){};
virtual void bar(){};
};
编译器可能会最终作出这样的:
所以一个成员函数指针到一个虚拟函数实际上需要是一个指数到虚拟表。 所以一个成员函数指针实际上需要1)可能是一个函数指针,2)可能是一个调整this
指针,和3)可能是一个虚函数表索引。 要一致,每一个成员函数指针需要能够所有这些的。 所以,这8
个字节的指针, 4
字节用于调整, 4
个字节的索引,对于16
字节总。
我认为这是一件真正改变编译器之间的很多,而且有很多可能的优化。 也许没有真正实现它我所描述的方式。
对于很多的细节,请参见本 (滚动到“成员函数指针的实现”)。
Basicly因为他们需要支持多态行为。 见一个很好的文章由雷蒙德陈。
一些解释可以在这里找到: 成员函数指针的底层表示
虽然成员指针行为像普通指针,在幕后他们的表现是完全不同的。 事实上,一个指针构件通常包括最多含在某些情况下四个字段struct的。 这是因为成员指针必须支持不仅普通成员函数,而且虚拟成员函数中,具有多个基类的对象的成员函数,和虚拟基类的成员函数。 因此,最简单的成员函数可以被表示为一组两个指针:一个保持所述成员函数的物理存储器地址,和保持该指针的第二指示器。 然而,在像一个虚拟成员函数,多重继承和虚拟继承的情况下,指针构件必须存储额外的信息。 因此,你不能施放成员指针普通指针也无法将安全地转换到不同类型的成员指针之间。 大段引用
我猜它是与this
指针......也就是说,每个成员函数也必须为他们在类的指针。然后将鼠标指针,使功能尺寸大一点。
一些主要的原因用于表示指针构件用作{this, T (*f)()}
是:
它在编译器比实现指针构件用作简单的实现T (*f)()
它不涉及运行时代码生成,也不额外簿记
它执行相当好相比T (*f)()
不存在从C ++程序员为指针成员函数的大小足够的需求等于sizeof(void*)
在执行过程中的运行时代码生成是事实上的一个为C ++代码忌讳目前
文章来源: Why the size of a pointer to a function is different from the size of a pointer to a member function?