(是的,我知道一条机器指令通常无关紧要。我问这个问题是因为我想了解 pimpl 成语,并以最好的方式使用它;而且有时我确实关心一条机器指令。 )
在下面的示例代码中,有两个类,Thing
和
OtherThing
. 用户将包括“thing.hh”。
Thing
使用 pimpl 习惯用法来隐藏它的实现。
OtherThing
使用 C 风格——返回和获取指针的非成员函数。这种风格会产生更好的机器代码。我想知道:有没有办法使用 C++ 风格——即将函数变成成员函数——但仍然保存机器指令。我喜欢这种风格,因为它不会污染类外的命名空间。
注意:我只关注调用成员函数(在本例中为calc
)。我不是在看对象分配。
以下是我 Mac 上的文件、命令和机器代码。
事情.hh:
class ThingImpl;
class Thing
{
ThingImpl *impl;
public:
Thing();
int calc();
};
class OtherThing;
OtherThing *make_other();
int calc(OtherThing *);
东西.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;
}
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));
}
生成文件:
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
运行make
,然后查看机器代码。在我使用的 mac 上otool -tv thing.o | c++filt
。在 linux 上,我认为是objdump -d thing.o
. 这是相关的输出:
物质:: calc():
0000000000000000 MOVQ(%rdi),%RAX
0000000000000003 MOVL(%RAX),%EAX 00000000000000000005 含量
含量
000000000000000000000007 ret
calc(earthting*) 0000000000000014 ret
由于指针间接,请注意额外的指令。第一个函数查找两个字段(impl,然后是 x),而第二个函数只需要获取 x。可以做什么?