2011-08-13 6 views
11

Việc sử dụng con trỏ "này" có thêm hoạt động khác vào chương trình khi chạy không?Có sự khác biệt nào giữa việc sử dụng con trỏ "này" và không sử dụng nó?

Chỉ cần đưa ra một ví dụ để giải thích các câu hỏi tốt hơn:

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

private: 
    int x; 
}; 

Liệu các chức năng "C :: set_x()", trong thời gian chạy, thực hiện 1 ít hoạt động hơn là "C :: set_this_x()" ?

Cảm ơn! :-)

Trả lời

19

Không có sự khác biệt giữa hai hàm thành viên. Nó phải được, vì đây là những gì C++ Standard (tiêu chuẩn ISO/IEC 14882: 2003) đã nói:

9.3.1 hàm thành viên không tĩnh [class.mfct.nonstatic]

2. Khi số id-expression (5.1) không phải là một phần của một thành viên lớp cú pháp truy cập (5.2.5) và không được sử dụng để tạo thành con trỏ tới thành viên (5.3.1) được sử dụng trong nội dung của một hàm thành viên không phải là thành viên của lớp X hoặc được sử dụng trong các mem-initializer cho một nhà xây dựng của lớp X, nếu nam e tra cứu (3.4.1) giải quyết các tên trong id-expression cho một thành viên không do type không tĩnh của lớp X hoặc của một lớp cơ sở của X, các id-expression được chuyển thành một biểu thức truy cập thành viên lớp (5.2.5) sử dụng (*this) (9.3.2) dưới dạng biểu thức hậu tố ở bên trái của toán tử .. Tên thành viên sau đó đề cập đến các thành viên của đối tượng mà chức năng được gọi.

5.2.5 truy cập thành viên Class [expr.ref]

3. Nếu E1 có kiểu “con trỏ đến lớp X”, sau đó biểu thức E1->E2 được chuyển đổi sang các hình thức tương đương (*(E1)).E2;. ..

Vì vậy, đó có nghĩa là đoạn mã sau:

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

sẽ được chuyển thành mã sau theo 9.3.1/2 và 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; 
}; 

Để hiển thị rằng có thực sự là không có sự khác biệt, ít nhất là cho một trình biên dịch, đây là một sự so sánh side-by-side của disassembly của C::set_x()C::set_this_x() chức năng VC++ biên dịch phát ra với tối ưu hóa bị vô hiệu hóa (/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 

Lưu ý rằng trình biên dịch tạo ra chính xác cùng lắp ráp cho cả hai chức năng thành viên.

9

Không, nó không tạo sự khác biệt thời gian chạy, nó chỉ là cú pháp. Con trỏ this vẫn được truy cập trong hàm đầu tiên, nó chỉ được chỉ định ngầm thay vì rõ ràng.

Bằng cách này, mùi này giống như tối ưu hóa sớm - viết mã sạch đầu tiên, nhanh mã sau đó.

+0

+1: Mã sạch đầu tiên! – Johnsyweb

+0

Cảm ơn bạn đã trả lời! :-) Tôi chưa thực hiện bất kỳ tối ưu hóa nào, chỉ cần nghĩ đến những địa điểm có thể được thực hiện khi thời gian đến. Tôi đã bị đốt cháy một lần từ tối ưu hóa sớm, đã có đủ điều đó :-). – TCS

3

Không, không có sự khác biệt.
khi bạn giới thiệu thành viên trực tiếp, trình biên dịch thực sự bỏ qua nó qua this.

2

số

Nếu bạn tình cờ trên biểu rằng trong mã của ai đó, nó có thể có nguồn gốc từ một cái gì đó như thế này:

struct A 
{ 
    int x; 

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

Không khác biệt, trình biên dịch đã tự động tạo mã cho this-> Trong khi nó là cú pháp không cần thiết, có hai lý do chính đáng để sử dụng:

  • bằng trình chỉnh sửa hỗ trợ tự động hoàn thành. Khi bạn nhập "this->", trình chỉnh sửa bật lên một cửa sổ công cụ hiển thị danh sách các thành viên của lớp để chọn. Điều này có thể tăng tốc độ nhập và giúp tránh các lỗi biên dịch ngớ ngẩn do lỗi nhập.

  • nó giúp tránh phải tìm ra các tên đối số nhân tạo. Bạn có thể cho đối số cùng tên với thành viên của lớp: void set_x (int x) {this-> x = x; }.

3

Giống nhau. Tuy nhiên, "điều này" có thể được sử dụng để phân biệt trong một số trường hợp.

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

Một trong những lần điều quan trọng là khi bạn đưa biến cục bộ có cùng tên với thành viên lớp học. Ví dụ:

class Example { 

public: 

    int something(); 
    int somethingElse(); 

} 


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

Có những nơi trong lập trình mẫu mà bạn cần phải sử dụng để sử dụng 'this' là tốt. Grep cho 'this->' trong thư viện chuẩn C++ và bạn sẽ thấy rằng mã được xếp chồng với 'this->'. –

2

Bạn có thể nói foo thay vì this->foo chỉ là cú pháp. Không có sự khác biệt trong mã được biên dịch. Giống như tất cả các đường cú pháp, một số ít decry nó nhưng hầu hết tình yêu nó. Để xem nơi bạn đứng về vấn đề này, hãy thử sử dụng một ngôn ngữ như perl hoặc python mà không cung cấp đường cú pháp này. Mã Python được xếp chồng lên nhau với self.foo; trong mã OO perl bạn sẽ thấy self->foo khắp nơi. Nó có thể hơi mất tập trung.

6

Cú pháp this->member là cần thiết nếu bạn kế thừa từ một lớp mẫu:

+3

Một cái gì đó là cần thiết để vượt qua vấn đề mà 'x' là một tên không phụ thuộc, nhưng điều gì đó không nhất thiết phải là' this-> x'. Người ta có thể sử dụng 'sử dụng Base :: x' bên trong khai báo lớp hoặc sử dụng' int b = Base :: x; 'trong hàm' Derived :: whatever'. –

+0

Ví dụ này là sai vì 'Derived' không có lớp cơ sở phụ thuộc. –

+0

@Johannes: Tốt hơn? Nếu không, xin vui lòng sửa chữa. – fredoverflow