C++ 是(*i)。成员的效率低于i->;成员
拥有 假设没有重载运算符C++ 是(*i)。成员的效率低于i->;成员,c++,performance,dereference,C++,Performance,Dereference,拥有 假设没有重载运算符 哪一个更有效(如果有的话) (*p).name与p->name 在我脑后的某个地方,我听到一些铃声响起,*解引用操作符可能会创建一个对象的临时副本;这是真的吗 这个问题的背景是这样的情况: struct Person { string name; }; Person* p = ... 我开始怀疑,如果将结果更改为Person*,并将最后一行简单地返回此是否会产生任何差异(在性能上)?没有区别。甚至标准都说这两个版本是等效的,如果有任何编译器不能为两个版本生
哪一个更有效(如果有的话)
(*p).name
与p->name
在我脑后的某个地方,我听到一些铃声响起,*
解引用操作符可能会创建一个对象的临时副本;这是真的吗
这个问题的背景是这样的情况:
struct Person {
string name;
};
Person* p = ...
我开始怀疑,如果将结果更改为
Person*
,并将最后一行简单地返回此
是否会产生任何差异(在性能上)?没有区别。甚至标准都说这两个版本是等效的,如果有任何编译器不能为两个版本生成相同的二进制文件,那就是一个糟糕的编译器。任何好的编译器都会产生相同的结果。您可以自己回答这个问题,将两个代码编译到汇编程序并检查生成的代码。当您返回引用时,这与传回指针完全相同,指针语义除外。您传回一个
sizeof(void*)
元素,而不是sizeof(yourClass)
所以当你这么做的时候:
Person& Person::someFunction(){
...
return *this;
}
返回一个引用,该引用与指针具有相同的内部大小,因此运行时没有差异
使用
(*i).name
也是如此,但是在这种情况下,您创建了一个,它与引用具有相同的语义(另请参见)是的,它更难阅读和键入,因此使用x->y
比使用(*x).y
要好得多-但是除了键入效率之外,这绝对没有区别。编译器仍然需要读取x
的值,然后将偏移量添加到y
,不管您使用的是一种形式还是另一种形式[当然,假设没有涉及覆盖运算符->
和运算符*
的有趣对象/类]
引用(*x)
时,肯定不会创建额外的对象。指针的值被加载到处理器[1]的寄存器中。就这样
返回引用通常效率更高,因为它返回指向对象的指针(伪装),而不是复制对象。对于大于指针大小的对象,这通常是一个胜利
(1)是的,我们可以为没有寄存器的处理器提供一个C++编译器。我在1984年看到的Rank Xerox中至少有一个处理器没有寄存器,它是一个专用的LiSP处理器,它只有一个LiSP对象堆栈。。。但它们在当今世界已不常见。如果有人在一个没有寄存器的处理器上工作,请不要因为我没有涵盖这个选项就否决我的答案。我尽量让答案简单
此时,您应该更加担心可读性,因为->
是更常见的语法糖,(*i).m
在许多地方都不受欢迎。只有当任何分析显示可能存在与此相关的问题时,您才应该开始担心它的效率。我希望编译器产生完全相同的结果。您可以自己回答这个问题,将两个代码编译到汇编程序并检查生成的代码。我问这个问题是因为我描述的背景-许多基本运算符通常返回对self的引用,我经常看到它们返回*this
*p
是一个l值(您可以执行*p=something;
)。这怎么可能创建一个临时对象?@KalamarObliwy没有这种可能性。内置指针解引用运算符*
返回一个l值,指定指向的对象(您可以将其视为对该对象的引用)。内置类型和用户定义的???@kalamaroblobwy也一样,假设没有运算符重载,是的。对于标准智能指针(std::unique_ptr
,std::shared_ptr
),重载运算符的行为仍然相同。这是关于返回大小的一个很好的观点。你能解释一下,*p
本身做了什么吗?它的结果是一个Person&或Person,或const Person&?如果我阅读正确并且根据维基百科,您会得到一个引用对象地址的l值
:
Person& Person::someFunction(){
...
return *this;
}