当前位置:  开发笔记 > 编程语言 > 正文

虚拟继承的价格是多少?

如何解决《虚拟继承的价格是多少?》经验,为你挑选了1个好方法。

这似乎是一个基本问题,但我没有看到它问:

假设以下简单案例:

没有虚拟成员.

虚拟继承用于允许多个路径到同一个基础.

根据访问派生类最多的成员所需的时间,虚拟继承的价格是多少?特别是,如果存在非零价格,它是否仅适用于通过多个路径继承的成员或其他成员?



1> Richard Hodg..:

根据访问派生类最多的成员所需的时间,虚拟继承的价格是多少?

一个偏移量查找和一个添加(2个指令和一个内存提取)

特别是,如果存在非零价格,它是否仅适用于通过多个路径继承的成员或其他成员?

是的,即便如此也并非总是如此.如果编译器有足够的信息来证明访问不需要通过间接访问,则可以在编译时自由地使查找短路.

在这种情况下,确切地澄清确切可能是件好事. - Nicol Bolas

先生说得好.

这是一个证明这一点的例子.使用-O2和-S选项进行编译,以查看实施中的优化.

#include 
#include 

enum class proof {
    base,
    derived
};

// volatile forces the compiler to actually perform reads and writes to _proof
// Without this, if the compiler can prove that there is no side-effect  of not performing the write,
// it can eliminate whole chunks of our test program!

volatile proof _proof;

struct base
{
    virtual void foo() const {
        _proof = proof::base;
    }

    virtual ~base() = default;
};

struct derived : base
{
    void foo() const override {
        _proof = proof::derived;
    }
};

// factory function
std::unique_ptr make_base(const std::string&name)
{
    static const std::string _derived = "derived";

    // only create a derived if the specified string contains
    // "derived" - on my compiler this is enough to defeat the
    // optimiser

    if (name == _derived) {
        return std::make_unique();
    }
    else {
        return {};
    }
}

auto main() -> int
{
    // here the compiler is fully aware that p is pointing at a derived
    auto p = std::make_unique();

    // therefore the call to foo() is made directly (in fact, clang even inlines it)
    p->foo();

    // even here, the compiler 'knows' that b is pointing at a 'derived'
    // so the call to foo is made directly (and indeed on my compiler, completely
    // inlined)
    auto b = std::unique_ptr(new derived);
    b->foo();

    // here we assign a derived to b via indirect construction through a string.
    // Unless the compiler is going to track this string and follow the logic in make_base
    // (and on my compiler it does not) this will prevent the virtual call to foo() from
    // being turned into a direct call.
    // Therefore, this call will be made via the virtual function table of *b
    b = make_base("derived");
    if (b) {
        b->foo();
    }

    return 0;
}

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有