29. Xem xét việc nạp chồng toán tử để loại bỏ những chuyển đổi kiểu ngầm định

Estimated reading: 4 minutes 215 views

Tóm tắt

Đừng nhân đôi đối tượng một cách không cần thiết (lưỡi dao Occam): Chuyển đổi kiểu ngầm định mang lại sự tiện lợi về cú pháp (nhưng xem thêm Mục 40). Tuy nhiên, khi việc tạo ra đối tượng tạm thời là không cần thiết, và việc tối ưu hóa là hợp lý (xem Mục 8), bạn nên cung cấp các hàm nạp chồng có chữ ký khớp chính xác với các kiểu đối số phổ biến, để tránh các chuyển đổi ngầm định.

Thảo luận

Nếu bạn đang ở văn phòng và hết giấy, bạn sẽ làm gì? Tất nhiên, bạn đi tới chiếc máy photocopy quen thuộc và photo thêm vài bản từ một tờ giấy trắng. Nghe thì có vẻ lố bịch, nhưng trên thực tế các chuyển đổi ngầm định thường làm điều tương tự: tạo ra các đối tượng tạm thời một cách không cần thiết, chỉ để thực hiện một thao tác tầm thường trên đó rồi ngay lập tức vứt đi (xem Mục 40).

Ví dụ phổ biến, so sánh chuỗi:

				
					class String {
   //...
   String(const char* text);  // cho phép chuyển đổi ngầm định từ const char*
};

bool operator==(const String&, const String&);

// Ở đâu đó trong code:
if (someString == "Hello") { ... }				
			

Dựa trên định nghĩa ở trên, trình biên dịch sẽ dịch câu lệnh này như thể bạn đã viết:

				
					someString == String("Hello");				
			

Điều này có thể rất lãng phí, bởi vì bạn không cần phải copy toàn bộ ký tự của "Hello" chỉ để đọc so sánh. Giải pháp là định nghĩa thêm các hàm nạp chồng để tránh chuyển đổi:

				
					bool operator==(const String& lhs, const String& rhs);     // #1
bool operator==(const String& lhs, const char* rhs);       // #2
bool operator==(const char* lhs, const String& rhs);       // #3				
			

Thoạt nhìn có vẻ như trùng lặp nhiều, nhưng thực tế chỉ là trùng lặp chữ ký. Cả ba hàm trên thường sẽ gọi chung về cùng một hàm xử lý logic bên trong. Với những overload đơn giản như vậy, bạn khó mà phạm phải lỗi tối ưu hóa sớm (premature optimization) (xem Mục 8). Thậm chí, khi viết thư viện, đây là một thói quen đáng khuyến khích, vì bạn khó có thể dự đoán trước được kiểu dữ liệu nào sẽ thường xuyên xuất hiện trong đoạn code nhạy cảm về hiệu năng.

Tóm lại,

  • Chuyển đổi ngầm định tiện nhưng đôi khi lãng phí.

  • Nạp chồng hàm để tránh tạo object tạm không cần thiết.

  • Đặc biệt hữu ích khi viết thư viện (library) dùng chung.

(Chú ý rằng class String ở trên chỉ là ví du, thực tế std::string của C++ đã có nạp chồng toán tử tương tự như trên rồi).

Tham khảo

[Meyers96] §21 • [StroustrupOO] §11.4, §C6 • [SutterOO] §6

Link 

Leave a Comment

Chia sẻ:

29. Xem xét việc nạp chồng toán tử để loại bỏ những chuyển đổi kiểu ngầm định

Or copy link

CONTENTS