我有MyClass的两个成员函数:

Result MyClass::func1( const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam1& extraParam1 )
{
    Result result;
    // prolog code, common to all, using commonParam1, commonParam2, commonParam3
    doSomething( 1, commonParam1, commonParam2, extraParam1 );
    // epilog code, common to all, using commonParam1, commonParam2, commonParam3
    return result;
}

Result MyClass::func2( const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam2& extraParam2, const ExtraParam3& extraParam3 )
{
    Result result;
    // prolog code, common to all, using commonParam1, commonParam2, commonParam3
    doSomething( 1, commonParam1, commonParam2, extraParam2, extraParam3 );
    // epilog code, common to all, using commonParam1, commonParam2, commonParam3
    return result;
}


我需要对此进行分解,以避免两个函数完全相同的prolog / epilog代码重复(修改了MyClass属性,prolog创建了Epilog使用的变量...类似的东西)。唯一的区别是调用了不同版本的MyClass::doSomething(具有不同的参数)。由于使用不同的参数集调用doSomething,因此我使用此方法使用模板进行分解,并引入了一个辅助类:

class helper1
{
public:
    helper1( const ExtraParam1& extraParam1 ) : extraParam1(extraParam1) {}
    inline bool compute( MyClass& parent, const CommonParam& commonParam1, const CommonParam& commonParam2 ) const
    {
        return parent.doSomething( 1, commonParam1, commonParam2, extraParam1 );
    }

private:
    const ExtraParam1& extraParam1;
};

class helper2
{
public:
    helper2( const ExtraParam2& extraParam2, const ExtraParam3& extraParam3 ) : extraParam2(extraParam2), extraParam3(extraParam3) {}
    inline bool compute( MyClass& parent, const CommonParam& commonParam1, const CommonParam& commonParam2 ) const
    {
        return parent.doSomething( 1, commonParam1, commonParam2, extraParam2, extraParam3 );
    }

private:
    const ExtraParam2& extraParam2;
    const ExtraParam3& extraParam3;
};

template<typename Helper>
inline Result funcT( MyClass& parent,
                     const CommonParam& commonParam1,
                     const CommonParam& commonParam2,
                     const CommonParam& commonParam3,
                     const Helper& helper )
{
    // this function is a friend of MyClass, so prolog/epilog can use any private class attribute

    Result result;
    // prolog code, common to all, using commonParam1, commonParam2, commonParam3
    helper.compute( parent, commonParam1, commonParam2 );
    // epilog code, common to all, using commonParam1, commonParam2, commonParam3
    return result;
}

Result MyClass::func1( const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam1& extraParam1 )
{
    return funcT( *this, commonParam1, commonParam2, commonParam3, helper1( *this, extraParam1) );
}

Result MyClass::func2( const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam2& extraParam2, const ExtraParam3& extraParam3 )
{
    return funcT( *this, commonParam1, commonParam2, commonParam3, helper2( *this, extraParam2, extraParam3 ) );
}


我们的算法将这些功能称为数十亿次,因此重构必须对运行时产生最小的影响。

computeinline,所有内容均通过引用传递,我使用模板而不是虚拟表来最大程度地减少对运行时间的影响。但是,我认为这会对运行时产生影响(至少我们创建helper1helper2对象)。

我的重构是否会对运行时产生影响,而编译器不会删除?
如果是,有人可以提出对运行时影响较小的重构吗?

最佳答案

我的重构是否会对运行时产生影响,而编译器不会删除?如果是,有人可以提出对运行时影响较小的重构吗?


确保不引入开销的唯一方法是衡量。在重构之前/之后分析您的代码,并检查生成的程序集。



作为附录,这是重构代码的一种稍微简单的方法,对于编译器来说,内联仍然应该很容易。与其存储对额外参数的引用,不如将它们完美地转发到一个通用的可调用对象:

template <typename TF, typename... TExtraParams>
Result MyClass::generic_func( const TF& doSomething, const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const TExtraParams&&... extraParams )
{
    Result result;
    // prolog code, common to all, using commonParam1, commonParam2, commonParam3
    doSomething( 1, commonParam1, commonParam2, std::forward<TExtraParams>(extraParams)... );
    // epilog code, common to all, using commonParam1, commonParam2, commonParam3
    return result;
}


在您当前的设计中,它可以按以下方式使用:

generic_func([](
    const CommonParam& a, const CommonParam& b, const CommonParam& c,
    const ExtraParam& extra0
)
{
    // ... will be called between prolog and epilog
}, my_a, my_b, my_c, extra0);

关于c++ - 可以在不影响运行时间的情况下分解此代码吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40038668/

10-13 03:57