【发布时间】:2011-02-22 06:10:34
【问题描述】:
(是的,我知道一条机器指令通常无关紧要。我问这个问题是因为我想了解 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 *);
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;
}
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
0000000000000005 包括 %eax
0000000000000007 ret
计算(其他事物*):
0000000000000010 movl (%rdi),%eax
0000000000000012 包括 %eax
0000000000000014 ret
注意由于指针间接导致的额外指令。第一个函数查找两个字段(impl,然后是 x),而第二个函数只需要获取 x。可以做什么?
【问题讨论】:
-
您是否在运行全面优化?
-
@the_drow:看看 Makefile。不,他不是。 @Rob:尝试使用
-O3进行编译……你有什么理由不使用完全优化? -
您必须在某个时候取消对指针的引用。没有办法绕过它。
-
使用 -O3 我得到相同的结果。
-
谢谢大家。我接受了 MSalters 的回答,因为它直接回答了我的问题。但正如马塞洛所说,该指令可能不会花费任何费用。我无法在我的计算机上检测到运行时间的差异。但我喜欢知道如何摆脱指令,以防万一我遇到测量表明它很重要的情况。 (如果我需要与 C 程序员讨论性能问题。:)
标签: c++ optimization pimpl-idiom