2010-07-05 6 views
19

Tôi muốn đảm bảo rằng tôi hiểu được giá trị theo từng giá trị so với giá trị tham chiếu vượt qua. Đặc biệt, tôi đang xem các phiên bản tiền tố/postfix của toán tử tăng thêm ++ cho một đối tượng.Nhà điều hành tăng số tiền tố/Postfix

Chúng ta hãy giả sử chúng ta có lớp sau X:

class X{ 
private: 
    int i; 
public: 
X(){i=0;} 
X& operator ++(){ ++i; return *this; } //prefix increment 

X operator ++ (int unused){ //postfix increment 
    X ret(*this); 
    i++; 
    return ret; 
} 

operator int(){ return i; } //int cast 
}; 

Trước hết, tôi đã thực hiện các prefix/nhà khai thác tăng postfix đúng cách?

Thứ hai, hiệu quả của bộ nhớ là toán tử postfix, so với toán tử tiền tố? Cụ thể có bao nhiêu bản sao đối tượng X được tạo khi mỗi phiên bản của toán tử được sử dụng?

Giải thích chính xác điều gì xảy ra với giá trị trả lại theo tham chiếu so với giá trị trả lại theo giá trị có thể giúp tôi hiểu.


Chỉnh sửa: Ví dụ, với đoạn mã sau ...

X a; 
X b=a++; 

... là a và b tại bí danh?

+0

Không cần tăng thêm hậu tố 'i' trong toán tử postfix. Trong thực tế, tôi sẽ làm như [FredOverflow gợi ý] (http://stackoverflow.com/questions/3181211/3181359#3181359) và gọi phiên bản tiền tố. IMO thực sự là thành ngữ hơn là tái thực hiện tăng (mặc dù việc thực hiện là tầm thường ở đây). _Và loại bỏ nhà điều hành chuyển đổi tiềm ẩn đó._ Nó sẽ làm tổn thương bạn nếu không. (Lần thứ ba và lần cuối tôi viết một nhà điều hành chuyển đổi tiềm ẩn là vào năm 2001 và một hoặc hai năm sau, tôi phát hiện ra rằng nó gây ra các lỗi tinh vi và loại bỏ nó - giống như tất cả những lỗi trước đây. BTDTGTLS.) – sbi

Trả lời

17

Đây là cách triển khai chính xác. Nó là điển hình mà một toán tử postfix sẽ tồi tệ hơn về hiệu suất vì bạn phải tạo một bản sao khác trước khi thực hiện tăng (và đây là lý do tại sao tôi đã có thói quen luôn sử dụng tiền tố trừ khi tôi cần cái gì khác).

Với tham chiếu trả về, bạn sẽ trả lại tham chiếu giá trị l cho đối tượng hiện tại. Trình biên dịch thường sẽ thực hiện điều này bằng cách trả về địa chỉ của đối tượng hiện tại. Điều này có nghĩa là trả về đối tượng cũng đơn giản như trả về một số.

Tuy nhiên, với trả lại theo giá trị, bạn phải sao chép. Điều này có nghĩa là có nhiều thông tin hơn để sao chép trong quá trình trả lại (thay vì chỉ là một địa chỉ) cũng như một trình tạo bản sao để gọi. Đây là nơi hiệu suất của bạn đạt được.

Hiệu quả của việc triển khai của bạn trông ngang bằng với các triển khai điển hình.

EDIT: Liên quan đến phụ lục của bạn, không, chúng không phải là bí danh. Bạn đã tạo ra hai đối tượng riêng biệt. Khi bạn trở lại theo giá trị (và khi bạn tạo một đối tượng mới từ bên trong toán tử tăng thêm postfix), đối tượng mới này được đặt trong một vị trí bộ nhớ riêng biệt.

Tuy nhiên, trong các mã, a và b sau bí danh:

int a = 0; 
int& b = ++a; 

b là một địa chỉ mà tham chiếu đến.

+2

Tối ưu hóa (http://en.wikipedia.org/wiki/Return_value_optimization). –

2

Các toán tử của bạn được triển khai chính xác.

Trong toán tử tiền tố, không có bản sao nào của X được tạo.

Trong toán tử postfix, một bản sao được thực hiện để ret và có khả năng một bản sao khác được thực hiện khi trở về từ hàm, nhưng tất cả trình biên dịch sẽ tách bản sao này.

15

Đây là thành ngữ hơn để gọi thặng dư tiền tố của đối tượng tự trong increment postfix:

X operator++(int) 
{ 
    X copy(*this); 
    ++*this;   // call the prefix increment 
    return copy; 
} 

Logic của incrementing một đối tượng X là như vậy, chỉ chứa bên trong phiên bản tiền tố.

+0

Vâng, điều này giải phóng tôi khỏi việc đăng chỉnh sửa tương tự. '+ 1' từ tôi. – sbi