虚拟指针的大小-C ++

时间:2009-10-21 23:14:47

标签: c++ pointers vtable

C ++中虚拟表的虚拟指针(VPTR)的大小是多少?这也不是一个家庭作业问题......在我阅读C ++书籍时,我想到了一个问题。

6 个答案:

答案 0 :(得分:6)

与此主题相关的优秀文章是Member Function Pointers and the Fastest Possible C++ Delegates。本文深入研究了许多不同编译器的成员函数指针的实现。本文讨论了vtable指针的所有细微差别,特别是考虑到多重(和虚拟)继承。

答案 1 :(得分:3)

请注意,为了优雅地处理多重继承,对象中可以有多个VPTR,但通常每个都可能是一个简单的体系结构相关指针。

尝试运行类似这样的内容,看看你的编译器如何解决问题:

#include <iostream>
using namespace std;

struct Base
{
    int B;
    virtual ~Base() {} 
};

struct Base2
{
    int B2;
    virtual ~Base2() {} 
};

struct Derived : public Base, public Base2
{
    int D;
};

int main(int argc, char* argv[])
{
    cout << "Base:" << sizeof (Base) << endl;
    cout << "Base2:" << sizeof (Base2) << endl;
    cout << "Derived:" << sizeof (Derived) << endl;

    Derived *d = new Derived();
    cout << d << endl;
    cout << static_cast<Base*>(d) << endl;
    cout << &(d->B) << endl;
    cout << static_cast<Base2*>(d) << endl;
    cout << &(d->B2) << endl;
    cout << &(d->D) << endl;
    delete d;
    return 0;
}

在我的32位编译器上,这为两个基类提供8个字节,为Derived类提供20个字节(并在编译为64位时将这些值加倍):

4 bytes Derived/Base VPTR
4 bytes int B
4 bytes Derived/Base2 VPTR
4 bytes int B2
4 bytes int D

您可以通过查看前8个字节来了解如何将Derived视为Base,以及如何通过查看后8个字节,您可以将其视为Base2。

答案 2 :(得分:2)

这取决于您的实施,但很容易找到。对于这个程序

#include <iostream>

struct virtual_base {
    int data;
    virtual_base() {}
    virtual ~virtual_base() {}
};

struct non_virtual_base {
    int data;
    non_virtual_base() {}
    ~non_virtual_base() {}
};

int main() {
    std::cout << sizeof( virtual_base ) - sizeof( non_virtual_base ) << '\n';
    return 0;
}
我的(VC 2008)将打印4,因此多态性的成本在这种情况下是4字节。

答案 3 :(得分:1)

可能与普通指针的大小相同...通常是32位机器上的4个字节。但这将依赖于编译器,一些编译器可能会以不同的方式做事。

答案 4 :(得分:1)

很可能是任何其他指针的大小。尝试这样的东西来找到你的编译器和机器:

#include <iostream>
struct base {
    base() {}
    virtual ~base() {}
};
int main( int argc, char **argv ) {
    std::cout << sizeof( base ) << std::endl;
}

答案 5 :(得分:1)

虚函数表中的指针通常与系统中常规指针的大小相同。通常,为每种类型计算虚函数表,并且每个对象实例将包含指向其类型表的指针,因此包含虚函数的对象实例将比每个实例使用sizeof(void *)个字节多。从多个基类型派生的类型必须可转换为任何基类型,因此可以根据需要包含指向基类型的虚函数表的多个指针。当然,所有这些都取决于编译器。