使用指针和不使用指针"this"有区别吗?

Is there a difference between using "this" pointer and not using it?

本文关键字:指针 有区别 this      更新时间:2023-10-16

是否使用"this"指针在运行时为程序增加了另一个操作?

只是为了更好地解释这个问题:

class C
{
public:
    void set_x(int val){ x = val; }
    void set_this_x(int val){ this->x = val; }
private:
    int x;
};

函数"C::set_x()"在运行时比"C::set_this_x()"少执行1次操作吗?

?

谢谢!: -)

这两个成员函数没有区别。它必须是,因为这是c++标准(ISO/IEC 14882:2003)必须说的:

9.3.1非静态成员函数[class.mfct.nonstatic]

2。id-expression(5.1)不是类成员的一部分时访问语法(5.2.5),不能用于形成指向成员的指针(5.3.1)。在类X或?的非静态成员函数体中使用mem-initializer中用于X类的构造函数,如果名称lookup(3.4.1)将id-expression中的名称解析为非静态的类XX基类的非类型成员id-expression被转换为类成员访问表达式(5.2.5)使用(*this)(9.3.2)作为左侧的后缀表达式.操作符。类的成员对象。

5.2.5类成员访问(expr.ref)

3。如果E1的类型是"指向类X的指针",则表达式E1->E2被转换成等价形式(*(E1)).E2;

这意味着下面的代码:

class C
{
public:
    void set_x(int val) { x = val; }
    void set_this_x(int val) { this->x = val; }
private:
    int x;
};

将根据9.3.1/2和5.2.5/3转换为以下代码:

class C
{
public:
    void set_x(int val)      { (*this).x = val; }   // as per 9.3.1/2
    void set_this_x(int val) { (*(this)).x = val; } // as per 5.2.5/3
private:
    int x;
};

为了表明它们之间没有区别,至少对于一个编译器来说,下面是vc++编译器在禁用优化(/Od)的情况下对C::set_x()C::set_this_x()函数的反汇编的并排比较:

  void set_x(int val){ x = val; }      void set_this_x(int val){ this->x = val; }
push      ebp                        push      ebp
mov       ebp,esp                    mov       ebp,esp
sub       esp,0CCh                   sub       esp,0CCh
push      ebx                        push      ebx
push      esi                        push      esi
push      edi                        push      edi
push      ecx                        push      ecx
lea       edi,[ebp-0CCh]             lea       edi,[ebp-0CCh]
mov       ecx,33h                    mov       ecx,33h
mov       eax,0CCCCCCCCh             mov       eax,0CCCCCCCCh
rep stos  dword ptr es:[edi]         rep stos  dword ptr es:[edi]
pop       ecx                        pop       ecx
mov       dword ptr [ebp-8],ecx      mov       dword ptr [ebp-8],ecx
mov       eax,dword ptr [this]       mov       eax,dword ptr [this]
mov       ecx,dword ptr [val]        mov       ecx,dword ptr [val]
mov       dword ptr [eax],ecx        mov       dword ptr [eax],ecx
pop       edi                        pop       edi
pop       esi                        pop       esi
pop       ebx                        pop       ebx
mov       esp,ebp                    mov       esp,ebp
pop       ebp                        pop       ebp
ret       4                          ret       4

注意,编译器为两个成员函数生成了完全相同的程序集。

不,这不会造成运行时差异,只是语法不同。this指针仍然在第一个函数中被访问,它只是隐式地指定,而不是显式地指定。

顺便说一下,这听起来像是一个过早的优化——先写干净的代码,再写快速的代码。

如果从类模板继承,则需要this->member语法:

template<typename T>
class Base
{
protected:
    T x;
};
template<typename T>
class Derived : Base<T>
{
public:
    void whatever()
    {
        T a = x;         // error
        T b = this->x;   // ok
    }
};

不,没有区别。
当你直接引用一个成员时,编译器实际上是通过this来解引用它。

是一样的。然而,在某些情况下,"this"可以用来消除歧义。

class C
{
public:
    void set_x(int x){ x = x; } // does nothing
    void set_this_x(int x){ this->x = x; } // sets the variable
private:
    int x;
};

No。

如果你在别人的代码中偶然发现了这个表达式,它很可能起源于这样的地方:

struct A
{
    int x;
    void set_X(int x)
    {
        this->x = x;
    }
};

没有区别,编译器已经自动为此生成代码->虽然它是多余的语法,但有两个很好的理由使用它:

  • 使用支持自动完成的编辑器。当您输入"this->"时,编辑器会弹出一个工具窗口,显示可供选择的类成员列表。这可以加快输入速度,并有助于避免由于输入错误而导致的愚蠢的编译错误。

  • 它有助于避免不得不提出人为的参数名称。你可以给实参赋予与类成员相同的名称:void set_x(int x) {this->x = x;} .

你可以说foo而不是this->foo只是语法上的糖。编译后的代码没有区别。像所有语法糖一样,一小部分人谴责它,但大多数人喜欢它。要了解您在这个问题上的立场,请尝试使用不提供这种语法糖的语言,如perl或python。Python代码中充斥着self.foo;在perl OO代码中,您将看到到处都是self->foo。它可能会让人分心。

当您为局部变量赋予与类成员相同的名称时,这一点很重要。例如:

class Example {
public:
    int something();
    int somethingElse();
}

int Example::somethingElse() {
    int something = something(); // ERROR
    int something = this->something(); // OK
    // ...
}