(*i).member 是不是比 i->member 效率低
Posted
技术标签:
【中文标题】(*i).member 是不是比 i->member 效率低【英文标题】:Is (*i).member less efficient than i->member(*i).member 是否比 i->member 效率低 【发布时间】:2013-04-27 15:43:17 【问题描述】:拥有
struct Person
string name;
;
Person* p = ...
假设没有运算符被重载。
哪个更有效(如果有的话)?
(*p).name
对比 p->name
在我脑后的某个地方,我听到一些铃声响起,*
取消引用运算符可能会创建对象的临时副本;这是真的吗?
这个问题的背景是这样的:
Person& Person::someFunction()
...
return *this;
我开始怀疑,将结果更改为 Person*
并将最后一行更改为简单的 return this
是否会产生任何影响(在性能方面)?
【问题讨论】:
此时您应该更加担心可读性,并且由于->
是更常见的语法糖,(*i).m
在许多地方都令人不悦。只有当任何分析表明可能存在与此相关的问题时,您才应该开始担心其效率。
我希望编译器产生完全相同的结果。您可以自己回答这个问题,将两个代码编译成汇编器并检查生成的代码。
我问这个问题是因为我描述的背景 - 许多基本运算符通常返回对自我的引用,我经常看到它们返回*this
;
*p
是一个左值(你可以做*p = something;
)。这怎么会创建一个临时对象?
@KalamarObliwy 没有这种可能性。内置指针解引用运算符*
返回一个左值,指定指向的对象(您可以将其视为对它的引用)。
【参考方案1】:
没有区别。甚至标准都说两者是等价的,如果有任何编译器不能为两个版本生成相同的二进制文件,那就太糟糕了。
【讨论】:
内置类型和用户自定义的一样吗?? @KalamarObliwy 假设没有运算符重载,是的。 对于标准智能指针(std::unique_ptr
、std::shared_ptr
),重载的操作符的行为仍然相同。【参考方案2】:
当您返回一个引用时,这与返回一个指针完全相同,指针语义除外。
你传回 sizeof(void*)
元素,而不是 sizeof(yourClass)
。
所以当你这样做时:
Person& Person::someFunction()
...
return *this;
您返回一个引用,并且该引用具有与指针相同的内在大小,因此没有运行时差异。
同样适用于 (*i).name
,但在这种情况下,您将创建一个 l-value,它与引用具有相同的语义(另请参阅 here)
【讨论】:
这是关于回报大小的一个好点。你能解释一下,*p
自己做了什么吗?它的结果是 Person& 或 Person,还是 const Person&?
如果我正确阅读 ***.com/questions/11347111/… 并根据***:en.wikipedia.org/wiki/Value_(computer_science),您会得到一个 l-value
,它引用了对象的地址【参考方案3】:
是的,阅读和打字要困难得多,所以使用x->y
比使用(*x).y
好得多 - 但除了打字效率之外,绝对没有区别。编译器仍然需要读取x
的值,然后将偏移量添加到y
,无论您使用一种形式还是另一种形式[假设没有涉及覆盖operator->
和operator*
的有趣对象/类当然,分别]
在引用(*x)
时肯定不会创建额外的对象。指针的值被加载到处理器 [1] 中的寄存器中。就是这样。
返回引用通常更有效,因为它返回指向对象的指针(变相),而不是复制对象。对于大于指针大小的对象,这通常是一个胜利。
[1] 是的,我们可以为没有寄存器的处理器提供 C++ 编译器。我知道我在 1984 年左右看到的 Rank-Xerox 的至少一个处理器,它没有寄存器,它是一个专用的 LiSP 处理器,它只有一个用于 LiSP 对象的堆栈......但它们远非常见在现今世界里。如果有人在没有寄存器的处理器上工作,请不要仅仅因为我没有涵盖该选项而否决我的答案。我试图保持答案简单。
【讨论】:
【参考方案4】:任何好的编译器都会产生相同的结果。您可以自己回答这个问题,将这两个代码编译成汇编程序并检查生成的代码。
【讨论】:
以上是关于(*i).member 是不是比 i->member 效率低的主要内容,如果未能解决你的问题,请参考以下文章
C++error C2511: overloaded member function 'void (void)' not found in 'class'请大神指教