虚拟指针的大小-C++

发布于 2024-08-08 17:30:47 字数 75 浏览 4 评论 0原文

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

What is the size of virtual pointer(VPTR) for a virtual table in C++? Also this is not a homework question...just a question that came to my mind while I was reading a C++ book.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

愁以何悠 2024-08-15 17:30:47

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

An excellent article related to this topic is Member Function Pointers and the Fastest Possible C++ Delegates. This article delves deeply into the implementation of member function pointers for many different compilers. This article talks about all the nuances of vtable pointers particularly in light of multiple (and virtual) inheritance.

就此别过 2024-08-15 17:30:47

请注意,为了优雅地处理多重继承,一个对象中可以有多个 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 个字节,为派生类提供 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。

Note that in order to gracefully handle multiple inheritance, there can be more than one VPTR in an object, but in general each is likely to be a simple architecture dependent pointer.

Try running something like this to see how your compiler lays things out:

#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;
}

On my 32-bit compiler, this give 8 bytes for both Base classes, and 20 bytes for the Derived class (and double those values when compiled for 64 bits):

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

You can see how by looking at the first 8 bytes, you can treat a Derived as a Base, and how by looking at the second 8 bytes, you can treat it as a Base2.

分开我的手 2024-08-15 17:30:47

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

#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 个字节。

That depends on your implementation, but it's easy to find out. For this program

#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;
}

mine (VC 2008) will print 4, so the cost of polymorphism is, in this case, 4 byte.

攀登最高峰 2024-08-15 17:30:47

可能与普通指针的大小相同...在 32 位机器上通常为 4 个字节。但这取决于编译器,某些编译器可能会做不同的事情。

Probably the same size as a normal pointer... generally 4 bytes on 32-bit machines. But this would be compiler-dependent, some compilers may do things differently.

水水月牙 2024-08-15 17:30:47

最有可能的是任何其他指针的大小。尝试这样的方法来找出适合您的编译器和机器的信息:

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

Most likely the size of any other pointer. Try something like this to find out for your compiler and machine:

#include <iostream>
struct base {
    base() {}
    virtual ~base() {}
};
int main( int argc, char **argv ) {
    std::cout << sizeof( base ) << std::endl;
}
伤痕我心 2024-08-15 17:30:47

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

The pointers in the virtual function table are generally the same size as regular pointers in the system. Typically a virtual function table is calculated for every type, and each object instance will contain a pointer to its type's table, so instances of objects containing virtual functions will use sizeof(void *) bytes more per instance than ones that don't. Types deriving from multiple base types must be castable to any base type so may contain multiple pointers to the base types' virtual function tables as necessary. All of this is compiler dependent of course.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文