正在访问 c++成员类通过“this->member”比对“member”的隐式调用更快/更慢

发布于 2024-12-12 03:37:24 字数 201 浏览 0 评论 0原文

在我们的朋友谷歌上进行一番搜索后,我无法得到以下观点的明确看法。

我习惯用 this-> 来调用类成员。即使不需要,我发现它更明确,因为它在维护一些带有大量变量的繁重算法时很有帮助。

当我正在研究一种应该优化的算法时,我想知道使用 this-> 是否会改变运行时性能。

是吗?

After some searching on our friend google, I could not get a clear view on the following point.

I'm used to call class members with this->. Even if not needed, I find it more explicit as it helps when maintaining some heavy piece of algorithm with loads of vars.

As I'm working on a supposed-to-be-optimised algorithm, I was wondering whether using this-> would alter runtime performance or not.

Does it ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

入怼 2024-12-19 03:37:24

不,这两种情况下的调用完全相同。

No, the call is exactly the same in both cases.

怪异←思 2024-12-19 03:37:24

这没有什么区别。这是 GCC 的演示。来源是简单的类,但为了清楚起见,我将这篇文章限制为差异。

% diff -s with-this.cpp without-this.cpp
7c7
<         this->x = 5;
---
>         x = 5;

% g++ -c with-this.cpp without-this.cpp  

% diff -s with-this.o without-this.o   
Files with-this.o and without-this.o are identical

It doesn't make any difference. Here's a demonstration with GCC. The source is simple class, but I've restricted this post to the difference for clarity.

% diff -s with-this.cpp without-this.cpp
7c7
<         this->x = 5;
---
>         x = 5;

% g++ -c with-this.cpp without-this.cpp  

% diff -s with-this.o without-this.o   
Files with-this.o and without-this.o are identical
你对谁都笑 2024-12-19 03:37:24

zennehoy 已经给出了答案,这里是一个简单测试类的汇编代码(由 Microsoft C++ 编译器生成):

class C
{
    int n;
public:
    void boo(){n = 1;}
    void goo(){this->n = 2;}
};

int main()
{
   C c;
   c.boo();
   c.goo();

       return 0;
}

Visual Studio 中的反汇编窗口显示两个函数的汇编代码是相同的:

class C
{
    int n;
public:
    void boo(){n = 1;}
001B2F80 55                   push        ebp  
001B2F81 8B EC                mov         ebp,esp  
001B2F83 81 EC CC 00 00 00    sub         esp,0CCh  
001B2F89 53                   push        ebx  
001B2F8A 56                   push        esi  
001B2F8B 57                   push        edi  
001B2F8C 51                   push        ecx  
001B2F8D 8D BD 34 FF FF FF    lea         edi,[ebp-0CCh]  
001B2F93 B9 33 00 00 00       mov         ecx,33h  
001B2F98 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
001B2F9D F3 AB                rep stos    dword ptr es:[edi]  
001B2F9F 59                   pop         ecx  
001B2FA0 89 4D F8             mov         dword ptr [ebp-8],ecx  
001B2FA3 8B 45 F8             mov         eax,dword ptr [this]  
001B2FA6 C7 00 01 00 00 00    mov         dword ptr [eax],1  
001B2FAC 5F                   pop         edi  
001B2FAD 5E                   pop         esi  
001B2FAE 5B                   pop         ebx  
001B2FAF 8B E5                mov         esp,ebp  
001B2FB1 5D                   pop         ebp  
001B2FB2 C3                   ret  
...
--- ..\main.cpp -----------------------------
void goo(){this->n = 2;}
001B2FC0 55                   push        ebp  
001B2FC1 8B EC                mov         ebp,esp  
001B2FC3 81 EC CC 00 00 00    sub         esp,0CCh  
001B2FC9 53                   push        ebx  
001B2FCA 56                   push        esi  
001B2FCB 57                   push        edi  
001B2FCC 51                   push        ecx  
001B2FCD 8D BD 34 FF FF FF    lea         edi,[ebp-0CCh]  
001B2FD3 B9 33 00 00 00       mov         ecx,33h  
001B2FD8 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
001B2FDD F3 AB                rep stos    dword ptr es:[edi]  
001B2FDF 59                   pop         ecx  
001B2FE0 89 4D F8             mov         dword ptr [ebp-8],ecx  
001B2FE3 8B 45 F8             mov         eax,dword ptr [this]  
001B2FE6 C7 00 02 00 00 00    mov         dword ptr [eax],2  
001B2FEC 5F                   pop         edi  
001B2FED 5E                   pop         esi  
001B2FEE 5B                   pop         ebx  
001B2FEF 8B E5                mov         esp,ebp  
001B2FF1 5D                   pop         ebp  
001B2FF2 C3                   ret  

并且 main 中的代码:

    C c;
    c.boo();
    001B2F0E 8D 4D F8             lea         ecx,[c]  
    001B2F11 E8 00 E4 FF FF       call        C::boo (1B1316h)  
    c.goo();
    001B2F16 8D 4D F8             lea         ecx,[c]  
    001B2F19 E8 29 E5 FF FF       call        C::goo (1B1447h)  

Microsoft 编译器使用 <类成员调用默认使用 code>__thiscall 调用约定,并且 this 指针通过 ECX 寄存器传递。

Answer has been given by zennehoy and here's assembly code (generated by Microsoft C++ compiler) for a simple test class:

class C
{
    int n;
public:
    void boo(){n = 1;}
    void goo(){this->n = 2;}
};

int main()
{
   C c;
   c.boo();
   c.goo();

       return 0;
}

Disassembly Window in Visual Studio shows that assembly code is the same for both functions:

class C
{
    int n;
public:
    void boo(){n = 1;}
001B2F80 55                   push        ebp  
001B2F81 8B EC                mov         ebp,esp  
001B2F83 81 EC CC 00 00 00    sub         esp,0CCh  
001B2F89 53                   push        ebx  
001B2F8A 56                   push        esi  
001B2F8B 57                   push        edi  
001B2F8C 51                   push        ecx  
001B2F8D 8D BD 34 FF FF FF    lea         edi,[ebp-0CCh]  
001B2F93 B9 33 00 00 00       mov         ecx,33h  
001B2F98 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
001B2F9D F3 AB                rep stos    dword ptr es:[edi]  
001B2F9F 59                   pop         ecx  
001B2FA0 89 4D F8             mov         dword ptr [ebp-8],ecx  
001B2FA3 8B 45 F8             mov         eax,dword ptr [this]  
001B2FA6 C7 00 01 00 00 00    mov         dword ptr [eax],1  
001B2FAC 5F                   pop         edi  
001B2FAD 5E                   pop         esi  
001B2FAE 5B                   pop         ebx  
001B2FAF 8B E5                mov         esp,ebp  
001B2FB1 5D                   pop         ebp  
001B2FB2 C3                   ret  
...
--- ..\main.cpp -----------------------------
void goo(){this->n = 2;}
001B2FC0 55                   push        ebp  
001B2FC1 8B EC                mov         ebp,esp  
001B2FC3 81 EC CC 00 00 00    sub         esp,0CCh  
001B2FC9 53                   push        ebx  
001B2FCA 56                   push        esi  
001B2FCB 57                   push        edi  
001B2FCC 51                   push        ecx  
001B2FCD 8D BD 34 FF FF FF    lea         edi,[ebp-0CCh]  
001B2FD3 B9 33 00 00 00       mov         ecx,33h  
001B2FD8 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
001B2FDD F3 AB                rep stos    dword ptr es:[edi]  
001B2FDF 59                   pop         ecx  
001B2FE0 89 4D F8             mov         dword ptr [ebp-8],ecx  
001B2FE3 8B 45 F8             mov         eax,dword ptr [this]  
001B2FE6 C7 00 02 00 00 00    mov         dword ptr [eax],2  
001B2FEC 5F                   pop         edi  
001B2FED 5E                   pop         esi  
001B2FEE 5B                   pop         ebx  
001B2FEF 8B E5                mov         esp,ebp  
001B2FF1 5D                   pop         ebp  
001B2FF2 C3                   ret  

And the code in the main:

    C c;
    c.boo();
    001B2F0E 8D 4D F8             lea         ecx,[c]  
    001B2F11 E8 00 E4 FF FF       call        C::boo (1B1316h)  
    c.goo();
    001B2F16 8D 4D F8             lea         ecx,[c]  
    001B2F19 E8 29 E5 FF FF       call        C::goo (1B1447h)  

Microsoft compiler uses __thiscall calling convention by default for class member calls and this pointer is passed via ECX register.

梦归所梦 2024-12-19 03:37:24

语言的编译涉及多个层。

访问 member 作为 memberthis->memberMyClass::member 等之间的区别...是句法差异。

更准确地说,这是一个名称查找的问题,以及编译器的前端如何“找到”您所引用的确切元素。因此,您可以通过更精确来加速编译...尽管这不会引起注意(C++ 中涉及更多耗时的任务,例如打开所有这些包含)。

由于(在本例中)您引用的是同一元素,因此它应该无关紧要。


现在,解释性语言可以进行有趣的类比。在解释性语言中,名称查找将延迟到调用该行(或函数)的那一刻。因此,它可能会在运行时产生影响(尽管同样可能并不明显)。

There are several layers involved in the compilation of a language.

The difference between accessing member as member, this->member, MyClass::member etc... is a syntactic difference.

More precisely, it's a matter of name lookup, and how the front-end of the compiler will "find" the exact element you are referring to. Therefore, you might speed up compilation by being more precise... though it will be unnoticeable (there are much more time-consuming tasks involved in C++, like opening all those includes).

Since (in this case) you are referring to the same element, it should not matter.


Now, an interesting parallel can be done with interpreted languages. In an interpreted language, the name lookup will be delayed to the moment where the line (or function) is called. Therefore, it could have an impact at runtime (though once again, probably not really noticeable).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文