28. Nên sử dụng thể chính tắc cho “++”, “- -“. Nên sử dụng ở dạng tiền tố.

Estimated reading: 3 minutes 240 views

Tóm tắt

Nếu bạn định nghĩa ++c, thì cũng nên định nghĩa c++. Các toán tử tăng (++) và giảm (--) có chút phức tạp vì mỗi toán tử có cả dạng tiền tố (prefix) và hậu tố (postfix), với sự khác biệt nhỏ về ngữ nghĩa. Hãy định nghĩa operator++ và operator-- sao cho chúng bắt chước hành vi của toán tử dựng sẵn. Và trong code gọi, hãy ưu tiên dùng dạng tiền tố nếu bạn không cần giá trị cũ.

Thảo luận

Một câu đùa xưa về C++ là ngôn ngữ này được gọi là C++ chứ không phải ++C vì nó “được cải tiến” (tăng lên), nhưng nhiều người vẫn dùng nó như C (giá trị cũ). May thay, câu đùa này giờ đã lỗi thời, nhưng nó lại minh họa tốt sự khác biệt giữa hai dạng toán tử.

  • Với ++ và --, dạng hậu tố (postfix) trả về giá trị cũ,

  • Trong khi dạng tiền tố (prefix) trả về giá trị mới.

Cách chuẩn (canonical) là triển khai hậu tố dựa trên tiền tố. Ví dụ:

				
					T& T::operator++() {       // dạng tiền tố ++x
    // thực hiện tăng
    return *this;          // luôn trả về *this
}

T& T::operator--() {       // dạng tiền tố --x
    // thực hiện giảm
    return *this;          
}

T T::operator++(int) {     // dạng hậu tố x++
    T old(*this);          // nhớ giá trị cũ
    ++*this;               // gọi lại phiên bản tiền tố
    return old;            // trả về giá trị cũ
}

T T::operator--(int) {     // dạng hậu tố x--
    T old(*this);          // nhớ giá trị cũ
    --*this;               // gọi lại phiên bản tiền tố
    return old;            // trả về giá trị cũ
}
				
			

Trong code gọi, bạn nên dùng dạng tiền tố trừ khi bạn thật sự cần giá trị cũ trả về từ dạng hậu tố.

  • Dạng tiền tố có cùng ngữ nghĩa,

  • Không tốn thêm thao tác copy,

  • Và thường hiệu quả hơn một chút (do không cần tạo ra một đối tượng bản sao tạm thời).

Điều này không phải tối ưu sớm (premature optimization); nó là tránh tối ưu sai (premature pessimization) (xem Mục 9).

Ví dụ:

				
					int b = 5;

int a1 = ++b;  // prefix
// b = 6, a1 = 6

b = 5;         // reset lại
int a2 = b++;  // postfix
// a2 = 5, b = 6
				
			

Ngoại lệ

Một số framework đặc biệt (ví dụ expression templates) có thể bảo toàn ngữ nghĩa của các toán tử này theo những cách khác.

Tham khảo

[Cline99] §23.07-08 • [DewhurstO3] §87 • [Meyers96] §6 • [StroustrupOO] §19.3 • [SutterOO] §6, §20

Link 

Leave a Comment

Chia sẻ:

28. Nên sử dụng thể chính tắc cho “++”, “- -“. Nên sử dụng ở dạng tiền tố.

Or copy link

CONTENTS