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;
}