实现vptr的替代方案?

Man*_*niP 7 c++ compiler-construction micro-optimization compiler-optimization vptr

这个问题不是关于C++语言本身(即不是关于标准),而是关于如何调用编译器来实现虚函数的替代方案.

实现虚函数的一般方案是使用指向指针表的指针.

class Base {
     private:
        int m;
     public:
        virtual metha();
};
Run Code Online (Sandbox Code Playgroud)

等价地说C会是这样的

struct Base {
    void (**vtable)();
    int m;
}
Run Code Online (Sandbox Code Playgroud)

第一个成员通常是指向虚拟函数列表等的指针(应用程序无法控制的内存中的一块区域).在大多数情况下,这会在考虑成员之前花费指针的大小等等.因此在大约4个字节的32位寻址方案中等等.如果在应用程序中创建了40k多态对象的列表,则大约为40k x在任何成员变量等之前4个字节= 160k字节.我也知道这恰好是C++编译中最快和最常见的实现.

我知道多重继承很复杂(尤其是虚拟类,即菱形结构等).

另一种方法是将第一个变量作为vptrs表的索引id(等效于C,如下所示)

struct Base {
    char    classid;     // the classid here is an index into an array of vtables
    int     m;
}
Run Code Online (Sandbox Code Playgroud)

如果应用程序中的类总数小于255(包括所有可能的模板实例化等),则char足以保存索引,从而减少应用程序中所有多态类的大小(我排除了对齐问题)等).

我的问题是,在GNU C++,LLVM或任何其他编译器中是否有任何切换来执行此操作?或减少多态对象的大小?

编辑:我了解指出的对齐问题.还有一点,如果这是64位系统(假设为64位vptr),每个多态对象成员的成本约为8字节,那么vptr的成本就是内存的50%.这主要涉及大量创建的小型多态,所以我想知道如果不是整个应用程序,这个方案是否至少可以用于特定的虚拟对象.

era*_*ran 3

您的建议很有趣,但如果可执行文件由多个模块组成并在它们之间传递对象,则该建议将不起作用。鉴于它们是单独编译的(例如 DLL),如果一个模块创建一个对象并将其传递给另一个模块,而另一个模块调用虚拟方法 - 它如何知道引用的是哪个表classid?您将无法添加另一个模块,moduleid因为这两个模块在编译时可能不知道彼此。所以除非你使用指针,否则我认为这是一个死胡同......