Rob*_*b N 6 c++ optimization pimpl-idiom
(是的,我知道一台机器指令通常无关紧要.我问这个问题是因为我想了解pimpl习语,并以最好的方式使用它;而且因为有时我会关心一台机器指令.)
在下面的示例代码中,有两个类,Thing和
OtherThing.用户将包括"thing.hh".
Thing使用pimpl成语来隐藏它的实现.
OtherThing使用C样式 - 返回并获取指针的非成员函数.这种风格产生稍好的机器代码.我想知道:有没有办法使用C++风格 - 即,使函数成为成员函数 - 但仍然保存机器指令.我喜欢这种风格,因为它不会污染类外的命名空间.
注意:我只关注调用成员函数(在本例中calc).我不是在看对象分配.
下面是我的Mac上的文件,命令和机器代码.
thing.hh:
class ThingImpl;
class Thing
{
ThingImpl *impl;
public:
Thing();
int calc();
};
class OtherThing;
OtherThing *make_other();
int calc(OtherThing *);
Run Code Online (Sandbox Code Playgroud)
thing.cc:
#include "thing.hh"
struct ThingImpl
{
int x;
};
Thing::Thing()
{
impl = new ThingImpl;
impl->x = 5;
}
int Thing::calc()
{
return impl->x + 1;
}
struct OtherThing
{
int x;
};
OtherThing *make_other()
{
OtherThing *t = new OtherThing;
t->x = 5;
}
int calc(OtherThing *t)
{
return t->x + 1;
}
Run Code Online (Sandbox Code Playgroud)
main.cc(只是为了测试代码实际工作......)
#include "thing.hh"
#include <cstdio>
int main()
{
Thing *t = new Thing;
printf("calc: %d\n", t->calc());
OtherThing *t2 = make_other();
printf("calc: %d\n", calc(t2));
}
Run Code Online (Sandbox Code Playgroud)
Makefile文件:
all: main
thing.o : thing.cc thing.hh
g++ -fomit-frame-pointer -O2 -c thing.cc
main.o : main.cc thing.hh
g++ -fomit-frame-pointer -O2 -c main.cc
main: main.o thing.o
g++ -O2 -o $@ $^
clean:
rm *.o
rm main
Run Code Online (Sandbox Code Playgroud)
运行make然后查看机器代码.在Mac上我使用otool -tv thing.o | c++filt.在linux上我认为是objdump -d thing.o.以下是相关输出:
Thing :: calc():
0000000000000000 movq(%rdi),%rax
0000000000000003 movl(%rax),%eax
0000000000000005 incl%eax
0000000000000007 ret
calc(OtherThing*):
0000000000000010 movl(%rdi),%eax
0000000000000012 incl%eax
0000000000000014 ret
由于指针间接,请注意额外的指令.第一个函数查找两个字段(impl,然后是x),而第二个函数只需要获取x.可以做些什么?
一条指令很少花费很多时间来担心.首先,编译器可以将pImpl缓存在更复杂的用例中,从而在实际场景中分摊成本.其次,流水线架构使得几乎不可能预测时钟周期中的实际成本.如果您在循环中运行这些操作并计算差异,您将获得更加真实的成本概念.
不太难,只需在课堂上使用相同的技巧.任何中途不错的优化器都会内置琐碎的包装器.
class ThingImpl;
class Thing
{
ThingImpl *impl;
static int calc(ThingImpl*);
public:
Thing();
int calc() { calc(impl); }
};
Run Code Online (Sandbox Code Playgroud)