English 中文(简体)
避免虚拟职能
原标题:Avoiding virtual functions

因此,我恳切希望开设一系列课程,使每个成员都能够发挥同样的作用。 让我指出这一职能

void doYourJob();

最后,我要把所有这些班子放在同一个集装箱里,以便我能够穿过这些班子,并且每个班都做过。

显而易见的解决办法是,使一个具有职能的抽象类别。

 virtual void doYourJob();

但我犹豫不决。 这是一个花费时间的方案,虚拟功能会大大降低。 此外,这一功能是各班间相互共有的唯一东西,而且每组别都完全不同。

是否有办法避免使用具有虚拟功能的抽象类别,或者我是否必须放弃?

最佳回答

Virtual functions don t cost much. They are an indirect call, basically like a function pointer. What is the performance cost of having a virtual method in a C++ class?

如果你回过头来,每个呼吁的周期都计算在内,这就是你在职能呼吁中做的工作少之又少,而且你在业绩关键应用中再次要求你这样做,很可能需要采取一种不同的办法。

问题回答

If, 您需要速度,考虑在物体中填入“类型(识别)”号,并用开关声明选择特定类型的代码。 这样做可以避免完全使用间接费用,而只是在当地跳跃。 你赢得的快要快于此。 一种成本(从可维持性、重复依赖性等角度)是强迫(转换)特定功能的本地化。


IMPLEMENTATION

#include <iostream>
#include <vector>

// virtual dispatch model...

struct Base
{
    virtual int f() const { return 1; }
};

struct Derived : Base
{
    virtual int f() const { return 2; }
};

// alternative: member variable encodes runtime type...

struct Type
{
    Type(int type) : type_(type) { }
    int type_;
};

struct A : Type
{
    A() : Type(1) { }
    int f() const { return 1; }
};

struct B : Type
{
    B() : Type(2) { }
    int f() const { return 2; }
};

struct Timer
{
    Timer() { clock_gettime(CLOCK_MONOTONIC, &from); }
    struct timespec from;
    double elapsed() const
    {
        struct timespec to;
        clock_gettime(CLOCK_MONOTONIC, &to);
        return to.tv_sec - from.tv_sec + 1E-9 * (to.tv_nsec - from.tv_nsec);
    }
};

int main(int argc)
{
  for (int j = 0; j < 3; ++j)
  {
    typedef std::vector<Base*> V;
    V v;

    for (int i = 0; i < 1000; ++i)
        v.push_back(i % 2 ? new Base : (Base*)new Derived);

    int total = 0;

    Timer tv;

    for (int i = 0; i < 100000; ++i)
        for (V::const_iterator i = v.begin(); i != v.end(); ++i)
            total += (*i)->f();

    double tve = tv.elapsed();

    std::cout << "virtual dispatch: " << total <<     << tve <<  
 ;

    // ----------------------------

    typedef std::vector<Type*> W;
    W w;

    for (int i = 0; i < 1000; ++i)
        w.push_back(i % 2 ? (Type*)new A : (Type*)new B);

    total = 0;

    Timer tw;

    for (int i = 0; i < 100000; ++i)
        for (W::const_iterator i = w.begin(); i != w.end(); ++i)
        {
            if ((*i)->type_ == 1)
                total += ((A*)(*i))->f();
            else
                total += ((B*)(*i))->f();
        }

    double twe = tw.elapsed();

    std::cout << "switched: " << total <<     << twe <<  
 ;

    // ----------------------------

    total = 0;

    Timer tw2;

    for (int i = 0; i < 100000; ++i)
        for (W::const_iterator i = w.begin(); i != w.end(); ++i)
            total += (*i)->type_;

    double tw2e = tw2.elapsed();

    std::cout << "overheads: " << total <<     << tw2e <<  
 ;
  }
}

www.un.org/Depts/DGACM/index_french.htm

关于我的含水层系统:

~/dev  g++ -O2 -o vdt vdt.cc -lrt
~/dev  ./vdt                     
virtual dispatch: 150000000 1.28025
switched: 150000000 0.344314
overhead: 150000000 0.229018
virtual dispatch: 150000000 1.285
switched: 150000000 0.345367
overhead: 150000000 0.231051
virtual dispatch: 150000000 1.28969
switched: 150000000 0.345876
overhead: 150000000 0.230726

这表明,直线型号位数方法大约为(1.28-0.23)/(0.344 - 0.23)=9.2倍。 当然,这一系统的具体特征是测试/汇编旗帜和册;版本等,但一般是指示性的。


www.un.org/Depts/DGACM/index_spanish.htm 评论

必须指出,虽然虚拟功能称为间接费用是很少重要的,而只是用于所谓的三维功能(如采集器和设计器)。 即便如此,你也能够提供单一功能,以便一劳永逸地获得和确定全部物品,从而尽量减少成本。 人们对虚拟发送感到担忧的程度太大,在寻找宽松的替代品之前,情况说明也是如此。 他们的主要问题是,他们履行一条外线职能,尽管他们也使所执行的法典失去地方性,从而改变了海滩利用模式(更好或(更经常)更糟)。

我担心一系列<代码>动力学-cast。 休息室的检查会比虚拟功能更糟。 如果你再把他们扔到一个集装箱里,他们就需要有某种类型的共同点,因此,你也可以把它当作一种纯粹的虚拟基体。

在这种背景下,虚拟功能的发送并非都是如此:表面上看,对所提供的<条码>的调整,即<条码/条码>点和间接呼吁。

如果履约情况如此关键,你可能能够使用每个亚类的单独集装箱,独立处理每个集装箱。 如果发出命令,你就这么多回想,实际上的派遣可能更快。

如果你将所有这些物体重新储存在同一集装箱内,那么你要么重新不得不写出一个杂质的集装箱类型(低价和昂贵),你将不得不储存一个<代码>的集装箱,避免*(yuck!”),要么这些班子要通过继承相互连接。 如果你选择采用前两种办法中的任何一种,那么你就不得不有某种逻辑来审视集装箱中的每一部分,说明其类型,然后称之为适当的<代码>doYourJob(执行,而执行方式基本上是为了继承。

我强烈建议首先采用简单、直截了当的做法。 如果这足够快,那就大了! 你做了回答。 如果是 t,则使用其他一些办法。 由于费用原因,永远不会避免一种有用的语言特征,除非你有很好的证据来表明成本过高。





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签