Размер виртуального C++ указателя

Я знаю, что это старый пост, но я только что натолкнулся на него и должен сказать вам ... расширение ограничило мои возможности вызова определенных действий объекта. Сейчас я переписываю некоторые части кода, чтобы избавиться от нанесенного мне ущерба. Если я не пишу однофайловую программу, я не собираюсь снова использовать расширенный.

5
задан Shog9 9 March 2010 в 23:53
поделиться

6 ответов

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.

7
ответ дан 18 December 2019 в 11:58
поделиться

Это зависит от вашей реализации, но это легко выяснить. Для этой программы

#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 байта.

2
ответ дан 18 December 2019 в 11:58
поделиться

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.

3
ответ дан 18 December 2019 в 11:58
поделиться

Вероятно того же размера, что и у обычного указателя ... обычно 4 байта на 32-битных машинах. Но это будет зависеть от компилятора, некоторые компиляторы могут делать что-то по-другому.

1
ответ дан 18 December 2019 в 11:58
поделиться

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;
}
1
ответ дан 18 December 2019 в 11:58
поделиться

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.

1
ответ дан 18 December 2019 в 11:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: