【发布时间】:2014-02-20 16:36:41
【问题描述】:
使用基于策略的设计,EncapsulatedAlgorithm:
template< typename Policy>
class EncapsulatedAlgorithm : public Policy
{
double x = 0;
public:
using Policy::subCalculate;
void calculate()
{
Policy::subCalculate(x);
}
protected:
~EncapsulatedAlgorithm() = default;
};
可能有一个执行子计算的策略Policy。算法不需要子计算:在某些情况下可以使用它来加速算法收敛。所以,为了建模,假设有三个策略。
一个只是“记录”一些东西的人:
struct log
{
static void subCalculate(double& x)
{
std::cout << "Doing the calculation" << endl;
}
};
计算的:
struct calculate
{
static void subCalculate(double& x)
{
x = x * x;
}
};
和一个把他们都带到黑暗中捆绑他们的人:D - 这完全没有:
struct doNothing
{
static void subCalculate(double& x)
{
// Do nothing.
}
};
这是示例程序:
typedef EncapsulatedAlgorithm<doNothing> nothingDone;
typedef EncapsulatedAlgorithm<calculate> calculationDone;
typedef EncapsulatedAlgorithm<loggedCalculation> calculationLogged;
int main(int argc, const char *argv[])
{
nothingDone n;
n.calculate();
calculationDone c;
c.calculate();
calculationLogged l;
l.calculate();
return 0;
}
here 就是一个活生生的例子。我尝试在打开优化的情况下检查gcc 生成的汇编代码:
g++ -S -O3 -std=c++11 main.cpp
但我对汇编的了解不够,无法确定地解释结果 - 结果文件很小,我无法识别函数调用,因为所有策略的静态函数的代码都是内联的。
我可以看到,当没有为 main 函数设置优化时,有一个 call 和一个与 'doNothing::subCalculate' 相关的后续 leave
call _ZN9doNothing12subCalculateERd
leave
这是我的问题:
- 我从哪里开始学习才能阅读
g++ -S喷出的内容? - 空函数是否已优化,
main.s中的哪些行? - 这种设计可以吗?通常,实现一个什么都不做的函数是一件坏事,因为接口说的是完全不同的东西(
subCalculate而不是doNothing),但在策略的情况下,策略名称清楚地表明该函数不会做任何事物。否则我需要做类型特征的东西,比如enable_if,等等,只是为了排除一个函数调用。
【问题讨论】:
-
首先删除
iostream以获得最少的输出。如果我这样做并使用 -O3 编译示例并且没有调试信息,它实际上会减少到return 0:xorl %eax, %eax,它只是将 eax 寄存器设置为0通过对自身进行异或运算。 -
这个问题没有实质内容。如果编译器内联了一个函数,并且它是空的,那么实际上没有什么可以进一步优化的,所以在这个调用的其余优化阶段,no-op 会很好地完成。如果不允许内联,则不会优化调用。因此问题大致相当于:编译器会做一些本应在 beta 测试中发现并消除的极其愚蠢的事情吗?答案是“有时”:(
-
您可以使用带有
-fdump-tree-all的中间 Gimple 转储...(它会吐出数百个文件,但有些文件非常易读,具有类似 C 的语法)。另见MELT
标签: c++ gcc optimization