是(* i)。成员效率低于i->成员

时间:2013-05-03 09:20:06

标签: c++ performance dereference

具有

struct Person {
   string name;
};

Person* p = ...

假设没有运算符过载。


哪个更有效(如果有的话)?

(*p).name vs。 p->name

在我脑后的某个地方,我听到一些铃声响起,*取消引用操作员可能会创建一个对象的临时副本;这是真的吗?


这个问题的背景是这样的情况:

Person& Person::someFunction(){
    ...
    return *this;
}

我开始怀疑,如果将结果更改为Person*而最后一行只是return this会有什么不同(性能)?

4 个答案:

答案 0 :(得分:9)

没有区别。即使标准说这两个是等价的,如果那里有任何编译器都没有为这两个版本生成相同的二进制文件,那就太糟糕了。

答案 1 :(得分:8)

当您返回引用时,这与传回指针完全相同,指针语义被排除
您传回了sizeof(void*)元素,而不是sizeof(yourClass)

所以当你这样做时:

Person& Person::someFunction(){
    ...
    return *this;
}

您返回一个引用,该引用具有与指针相同的内在大小,因此没有运行时差异。

同样适用于(*i).name,但在这种情况下,您创建了一个l-value,其语义与引用相同(另请参阅here

答案 2 :(得分:2)

是的,阅读和打字要困难得多,所以使用x->y而不是(*x).y要好得多 - 但除了输入效率之外,绝对没有区别。编译器仍然需要读取x的值,然后将偏移量添加到y,无论是使用一种形式还是另一种形式[假设没有涉及的有趣对象/类覆盖{{1}当然,分别为{}和operator->

引用operator*时肯定没有创建额外的对象。指针的值被加载到处理器[1]中的寄存器中。就是这样。

返回引用通常更有效,因为它将指针(伪装)返回给对象,而不是制作对象的副本。对于大于指针大小的对象,这通常是一个胜利。

[1]是的,我们可以为没有寄存器的处理器配备C ++编译器。我知道Rank-Xerox中至少有一个处理器是我在1984年左右看到的,它没有寄存器,它是一个专用的LiSP处理器,它只有一个LiSP对象的堆栈......但它们远非常见在现今世界里。如果某人在没有注册表的处理器上工作,请不要仅仅因为我没有涵盖该选项而拒绝我的回答。我试图让答案变得简单。

答案 3 :(得分:1)

任何好的编译器都会产生相同的结果。您可以自己回答这个问题,将两个代码编译成汇编程序并检查生成的代码。