C++ (gcc)编译器是否优化了空体函数?
使用基于策略的设计,一种C++ (gcc)编译器是否优化了空体函数?,c++,gcc,optimization,C++,Gcc,Optimization,使用基于策略的设计,一种封装的算法: template< typename Policy> class EncapsulatedAlgorithm : public Policy { double x = 0; public: using Policy::subCalculate; void calculate() { Policy::subCalculate(x);
封装的算法
:
template< typename Policy>
class EncapsulatedAlgorithm : public Policy
{
double x = 0;
public:
using Policy::subCalculate;
void calculate()
{
Policy::subCalculate(x);
}
protected:
~EncapsulatedAlgorithm() = default;
};
计算的人计算:
struct calculate
{
static void subCalculate(double& x)
{
x = x * x;
}
};
有一个人把他们都带来,在黑暗中把他们捆绑起来:D-那是绝对没有用的:
以下是示例程序:
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;
}
但我对汇编的了解还不够,无法确定地解释结果——结果文件很小,我无法识别函数调用,因为所有策略的静态函数的代码都是内联的
我能看到的是,当没有为设置优化时,在主函数中,有一个调用
,以及一个与“doNothing::subCalculate”相关的后续离开
call _ZN9doNothing12subCalculateERd
leave
以下是我的问题:
g++-S
吐出的东西,我从哪里开始学习李>
main.s
中的什么位置subCalculate
,而不是doNothing
),但是在策略的情况下,策略名称清楚地表明该函数不会做任何事情。否则我需要做一些类型特征的事情,比如enable_if
,等等,只是为了排除单个函数调用李>
为了能够读懂g++-S所表达的内容,我从哪里开始学习
本网站不推荐阅读材料。谷歌“x86汇编语言”
空函数是否进行了优化?这些行在main.s中的什么位置
它将在启用Optimizer时出现,因此生成的.S中不会有任何行。您已经在未优化的输出中找到调用
事实上,即使是用于执行乘法的策略也可能被删除,因为编译器应该能够确定您没有使用结果值。添加代码以打印x的值,并从编译时无法知道的某个值中为x添加种子(在这样的小实验程序中使用argc通常很方便,然后您将强制编译器至少保留功能上重要的代码
这个设计可以吗
这取决于很多事情(例如,如果实现需要在头文件中公开,是否要使用模板,是否要为每个实例化处理不同的类型…),但是您正确地实现了设计
通常,实现一个不做任何事情的函数是一件坏事,因为接口说的是完全不同的东西(subCalculate而不是doNothing),但在策略的情况下,策略名称清楚地表明函数不会执行任何操作。否则,我需要执行诸如enable_if等类型特征,以排除单个函数调用
您可能需要仔细考虑函数名称…<代码> dothayii必需的计算()/<代码> <代码> EnSurReExpResiviVE()/<代码>而不是<代码> LoopyMutEXE()/代码>,<代码>后缀值>(代码)>而不是<代码> PrimtType < /代码>等。
< p>我到了,显示程序集输出。template< typename Policy>
struct EncapsulatedAlgorithm : public Policy
{
void calculate(double& x)
{
Policy::subCalculate(x);
}
};
struct doNothing
{
static void subCalculate(double& x)
{
}
};
void func(double& x) {
EncapsulatedAlgorithm<doNothing> a;
a.calculate(x);
}
嗯,我在那里的程序集中只看到两个操作码。
rep
(不知道那是什么)和结束函数。似乎G++编译器可以轻松地优化函数体。首先删除iostream
,以获得最小的输出。如果我这样做,并使用-O3编译示例,而不使用调试信息,它实际上会减少到返回0
:xorl%eax,%eax
,这只是将eax寄存器设置为0代码>通过xoring对其自身进行xoring。问题中没有实质内容。如果编译器内联一个函数,并且该函数为空,则实际上没有什么需要进一步优化的,因此在该调用的其余优化阶段,No op将很好地完成。如果不允许内联,则调用将不会优化。因此,问题大致相等与此相关:编译器会做一些本应在beta测试中捕获并消除的极其愚蠢的事情吗?答案是“有时”:(您可以将中间Gimple转储与-fdump tree all
…(它吐出数百个文件,但有些文件可读性很强,语法类似C)。另请参阅
g++ -S -O3 -std=c++11 main.cpp
call _ZN9doNothing12subCalculateERd
leave
template< typename Policy>
struct EncapsulatedAlgorithm : public Policy
{
void calculate(double& x)
{
Policy::subCalculate(x);
}
};
struct doNothing
{
static void subCalculate(double& x)
{
}
};
void func(double& x) {
EncapsulatedAlgorithm<doNothing> a;
a.calculate(x);
}
.Ltext0:
.globl _Z4funcRd
_Z4funcRd:
.LFB2:
.cfi_startproc #void func(double& x) {
.LVL0:
0000 F3 rep #not sure what this is
0001 C3 ret #}
.cfi_endproc
.LFE2:
.Letext0: