2009-10-21 6 views
4

C++의 가상 테이블에 대한 가상 포인터 (VPTR)의 크기는 얼마입니까? 또한 이것은 숙제 문제가 아닙니다 ... C++ 책을 읽는 동안 내 마음에 떠오른 질문입니다.가상 포인터의 크기 -C++

+0

분명히 숙제가 아닙니다. 강사들은 대개 학부 수준이 아닌 이러한 종류의 질문을하지 않습니다. – pyon

+0

어떤 포인터에 대해 이야기하고 있습니까? VPTR은 정확히 표준 명칭이 아닙니다. 각 객체에 저장된 * to *'vtbl' 포인터에 관심이 있습니까? 아니면'vtbl' * 자체를 구성하는 포인터에 관심이 있으십니까? – AnT

+1

@Leon : 또는 어떤 레벨에서나, 컴파일러 전반에서 공조가되지 않는 구현 세부 사항입니다. 또한 모든 컴파일러가 가상 함수를 구현하기 위해 V-Tables를 사용하는 것은 아닙니다 (단지 가장 쉬운 기술입니다). –

답변

5

이 주제와 관련된 우수 기사는 Member Function Pointers and the Fastest Possible C++ Delegates입니다. 이 기사에서는 여러 컴파일러에 대한 멤버 함수 포인터 구현에 대해 자세히 설명합니다. 이 기사에서는 복수 (가상) 상속에 비추어 볼 때 vtable 포인터의 모든 뉘앙스에 대해 설명합니다.

1

아마 일반적인 포인터와 같은 크기 ... 일반적으로 32 비트 컴퓨터에서는 4 바이트입니다. 그러나 이것은 컴파일러에 따라 다르며 일부 컴파일러는 상황을 다르게 할 수 있습니다.

1

대부분 다른 포인터의 크기입니다. 정상적으로 다중 상속을 처리하기 위해, 객체에 하나 이상의 vptr에서있을 수 있지만, 일반적으로 각이 될 가능성이 있음을

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

참고 : 컴파일러와 시스템에 대해 알아 이런 식으로 뭔가를 시도 간단한 아키텍처 의존적 인 포인터. 이 파생 클래스의 두 기본 클래스의 8 바이트, 20 바이트를주고, 내 32 비트 컴파일러에

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

을 (그리고 :

하면 컴파일러가 물건을 낳는 방법을 보려면 다음과 같이 뭔가를 실행 해보십시오 64 비트 용으로 컴파일 된 경우)이 값을 두 배로 :

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

당신은 처음 8 바이트를보고, 당신이이 자료로 파생 된 치료 방법을 참조하는 방법, 당신이 할 수있는 두 번째 8 바이트를보고 할 수 있습니다 그것을 Base2로 취급하십시오.

1

가상 함수 테이블의 포인터는 일반적으로 시스템의 일반 포인터와 같은 크기입니다. 일반적으로 가상 함수 테이블은 모든 유형에 대해 계산되며 각 객체 인스턴스에는 유형 테이블에 대한 포인터가 포함되므로 가상 함수가 포함 된 객체의 인스턴스는 인스턴스 당 sizeof(void *) 바이트를 사용하지 않습니다. 다중 기본 유형에서 파생 된 유형은 모든 기본 유형으로 3 스팅 할 수 있어야하므로 필요에 따라 기본 유형의 가상 함수 테이블에 대한 여러 포인터를 포함 할 수 있습니다. 이 모든 것은 물론 컴파일러에 의존합니다.

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 바이트입니다.