首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LTO、去虚拟化和虚拟表

LTO、去虚拟化和虚拟表
EN

Stack Overflow用户
提问于 2011-08-12 21:54:10
回答 4查看 6K关注 0票数 16

比较C++中的虚拟函数和C中的虚拟表,编译器(以及足够大的项目)在去虚拟化方面做得很好吗?

天真地说,似乎C++中的虚拟函数具有更多的语义,因此可能更容易去虚拟化。

更新: Mooing提到内联去虚拟化功能。快速检查显示没有使用虚拟表进行优化:

代码语言:javascript
复制
struct vtab {
    int (*f)();
};

struct obj {
    struct vtab *vtab;
    int data;
};

int f()
{
    return 5;
}

int main()
{
    struct vtab vtab = {f};
    struct obj obj = {&vtab, 10};

    printf("%d\n", obj.vtab->f());
}

我的GCC将不会内联f,虽然它被直接称为,即去虚拟化。C++中的等价物

代码语言:javascript
复制
class A
{
public:
    virtual int f() = 0;
};

class B
{
public:
    int f() {return 5;}
};

int main()
{
    B b;
    printf("%d\n", b.f());
}

即使是内联f,C和C++之间也有第一个不同之处,尽管我认为在C++版本中添加的语义在这种情况下并不相关。

更新2:为了在C中去虚拟化,编译器必须证明虚拟表中的函数指针有一定的值。为了在C++中进行去虚拟化,编译器必须证明对象是特定类的实例。在第一种情况下,证据似乎更难证明。但是,虚拟表通常只在很少的地方被修改,最重要的是:仅仅因为它看起来更难,并不意味着编译器在这方面没有那么好(否则,您可能会认为xoring通常比添加两个整数更快)。

EN

回答 4

Stack Overflow用户

发布于 2011-08-13 10:31:39

不同之处在于,在C++中,编译器可以保证虚拟表地址不会改变。在C中,它只是另一个指针,你可以用它造成任何形式的破坏。

然而,

通常只在很少的地方修改虚拟表。

编译器不知道在C中,在C++中,它可以假设它永远不会改变。

票数 9
EN

Stack Overflow用户

发布于 2014-01-29 16:14:14

我试图在http://hubicka.blogspot.ca/2014/01/devirtualization-in-c-part-2-low-level.html中总结一下为什么一般的优化很难去虚拟化。您的测试用GCC 4.8.1为我准备,但在稍微不那么简单的测试案例中,如果您将指向“对象”的指针从主目录中传递出来,则不会。

原因是为了证明obj中的虚拟表指针和虚拟表本身并没有改变别名分析模块,必须跟踪您可以指向它的所有可能的位置。在一个非平凡的代码中,在当前编译单元之外传递东西,这通常是一个失败的游戏。

C++为您提供了更多关于对象类型何时更改以及何时已知的信息。GCC利用它,它将在下一个版本中更多地使用它。(我很快也会写信的)。

票数 4
EN

Stack Overflow用户

发布于 2011-08-12 23:08:07

是的,如果编译器可以推断虚拟化类型的确切类型,那么它可以“去虚拟化”(甚至内联!)那个电话。编译器只能保证无论发生什么,这都是所需的函数,才能做到这一点。

主要关注的是线程处理。在C++示例中,即使在线程环境中,这些保证仍然有效。在C中,这是不能保证的,因为对象可以被另一个线程/进程抓取,并被覆盖(不管是有意的还是故意的),因此函数永远不会被“去虚拟化”或直接调用。在C中,查找将始终在那里。

代码语言:javascript
复制
struct A {
    virtual void func() {std::cout << "A";};
}
struct B : A {
    virtual void func() {std::cout << "B";}
}
int main() {
    B b;
    b.func(); //this will inline in optimized builds.
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7046739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档