3

英特尔 C++ 编译器将 vptr(指向虚函数表的指针)存储在对象中的什么位置?

我相信 MSVC 把它放在对象的开头, gcc 放在最后。icpc(英特尔 C++ 编译器)是什么?

4

5 回答 5

3

您始终可以查看此地址和派生类中的第一个地址所在的位置:

#include <stdio.h>

class foo
{
public:
    virtual int do_foo()=0;
};

class bar : public foo
{
public:
    int bar;
    int do_foo() {printf ("%08x %08x\n", this, &bar);}
};

int main()
{
    bar a_bar;
    a_bar.do_foo();
}

在我的 linux 机器上,结果是:

bfdbef3c bfdbef40

...这正是您所期望的:第一个指针加上虚函数指针的大小就是第二个指针的位置。

于 2009-04-01T23:16:05.657 回答
1

对于 Intel C++ 编译器,对于 Linux,我发现它是对象的开头。

代码:

#include <cstdio>

class A 
{
  int a, b;
public:
  A(int a1, int b1): a(a1), b(b1) {}
  virtual void p(void) { printf("A\n"); }
};

class B: public A
{
public:
  B(int a1, int b1): A(a1, b1) {}
  void p(void){ printf("B\n"); }
};

int main(void)
{
  A a(1, 2); int p=10; A a1(5, 6);
  B b(3, 4); int q=11; B b2(7, 8);

  a.p();
  b.p();

  int * x=(int*)&a;
  printf("%d %d %d %d\n", x[0], x[1], x[2], x[3]);
  x=(int*)&b;
  printf("%d %d %d %d\n", x[0], x[1], x[2], x[3]);
}
于 2009-04-02T00:10:28.193 回答
0

你是什​​么意思“在函数的开头”?无论如何,Windows 编译器将 vptr 放在对象的偏移量 0 处,而 Unix 编译器将它放在最后一个成员数据之后。英特尔为 Windows 和 Unix 生产编译器,我希望 Win 版本将 vptr 放在开头,将 *nix 版本放在对象的末尾。

于 2009-04-01T18:57:51.020 回答
0

vtable 指针在对象中的位置与操作系统无关。这只是编译器和其他工具的约定。

Sid Datta,您可以从 ICC 反汇编某些编译模块中发现该信息。

于 2009-04-01T23:03:32.380 回答
0

除了满足您的好奇心之外,您问题的真正答案不会很有用,因为 C++ 标准没有定义这样的细节。因此,任何编译器供应商都可以按照他们认为合适的方式实现这些功能。这也是 C++ 没有跨平台 ABI(应用程序二进制接口)的原因之一。

于 2009-04-06T03:00:22.910 回答