2011-08-13 85 views
11

使用「this」指針是否在運行時向程序添加了另一個操作?使用「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()」,在運行時間期間,執行操作比1以下 「C :: set_this_x()」 ?

謝謝! :-)

回答

19

這兩個成員函數沒有區別。它必須是,因爲這是C++標準(ISO/IEC 14882:2003)具有地說:

9.3.1非靜態成員函數[class.mfct.nonstatic]

2.當在非靜態成員函數的主體中使用不屬於類成員 訪問語法(5.2.5)且未用於形成指向成員(5.3.1) 的id-expression(5.1)時X或 用於mem-initializer中類X的構造函數,如果nam È 查找(3.4.1)可解決id-expression名稱X類或基類的X的非靜態 無類型部件,所述 id-expression被轉換成使用(*this)類成員訪問表達式 (5.2.5) (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; 
}; 

爲了證明真的是沒有區別的,至少一個編譯器,這裏的禁用C::set_x()C::set_this_x()功能VC++編譯器優化發出的拆卸的側方比較(/Od):

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 

注意,編譯器產生完全相同的組件兩個成員函數。

9

不,它不會產生運行時差異,它只是語法。 this指針仍然在第一個函數中訪問,它只是隱式指定而不是顯式指定的。順便說一下,這聽起來像一個過早的優化 - 先寫清潔代碼,稍後再寫快代碼。

+0

+1:清潔代碼第一! – Johnsyweb

+0

謝謝你的回答! :-) 我還沒有做出任何優化,只是想着時間到了的地方。我從過早的優化中被燒過一次,得到了足夠的:-)。 – TCS

3

不,沒有區別。
當您直接引用成員時,編譯器通過this實際取消它。

2

如果你在別人的代碼絆倒的表達,它可能起源於這樣的事:

struct A 
{ 
    int x; 

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

沒有區別,編譯器已經自動爲這 - 生成代碼>雖然是多餘的語法,有兩個很好的理由使用它:

  • 使用支持自動完成的編輯器。當你輸入「this->」時,編輯器彈出一個工具窗口,顯示可供選擇的類成員列表。這可以加快打字速度,並有助於避免由於輸入錯誤而導致的傻編譯錯誤。

  • 它有助於避免必須拿出虛假的參數名稱。你可以給參數和類成員同名:void set_x(int x){this-> x = x; }。

3

這是一樣的。但是,在某些情況下,可以使用「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; 
}; 
1

其中一個重要的時刻是當你給一個局部變量同名的類成員。例如:

class Example { 

public: 

    int something(); 
    int somethingElse(); 

} 


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

模板編程中有些地方需要使用'this'。 grep for C++標準庫中的'this->',你會發現代碼是用'this->'來完成的。 –

2

,你可以說foo,而不是this->foo只是語法糖。編譯後的代碼沒有區別。就像所有的語法糖一樣,一小部分人譴責它,但大多數人都喜歡它。要了解您在該問題上的立場,請嘗試使用不提供此語法糖的perl或python語言。 Python代碼充斥着self.foo;在perl OO代碼中,你會在整個地方看到self->foo。它可能有點分散注意力。如果你從一個類模板繼承

6

this->member語法要求:

+3

需要一些東西來解決'x'是一個非獨立名稱的問題,但某些不一定是'this-> x'。可以在類聲明中使用'使用Base :: x'或在函數Derived :: whatever中使用'int b = Base :: x;'。 –

+0

這個例子是錯誤的,因爲'Derived'沒有一個依賴的基類。 –

+0

@Johannes:好點?如果沒有,請修復。 – fredoverflow

相關問題