Có điều gì đó làm tôi khó chịu:
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
swap(tmp);
return *this;
}
Đầu tiên, đọc từ "hoán đổi" khi tâm trí tôi đang nghĩ "bản sao" làm tôi khó chịu. Ngoài ra, tôi đặt câu hỏi về mục tiêu của thủ thuật lạ mắt này. Có, bất kỳ ngoại lệ nào trong việc xây dựng các tài nguyên mới (được sao chép) sẽ xảy ra trước khi hoán đổi, đây có vẻ như là một cách an toàn để đảm bảo tất cả dữ liệu mới được lấp đầy trước khi đưa nó vào hoạt động.
Tốt rồi. Vì vậy, những gì về ngoại lệ xảy ra sau khi hoán đổi? (khi tài nguyên cũ bị hủy khi đối tượng tạm thời vượt ra khỏi phạm vi) Từ quan điểm của người sử dụng phép gán, hoạt động đã thất bại, ngoại trừ nó đã không. Nó có một tác dụng phụ rất lớn: bản sao đã thực sự xảy ra. Nó chỉ là một số tài nguyên dọn dẹp không thành công. Trạng thái của đối tượng đích đã được thay đổi mặc dù hoạt động từ bên ngoài có vẻ như đã thất bại.
Vì vậy, tôi đề xuất thay vì "hoán đổi" để thực hiện một "chuyển giao" tự nhiên hơn:
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
transfer(tmp);
return *this;
}
Vẫn còn việc xây dựng đối tượng tạm thời, nhưng hành động ngay lập tức tiếp theo là giải phóng tất cả tài nguyên hiện tại của đích trước khi di chuyển (và NULLing để chúng không bị giải phóng hai lần) tài nguyên của nguồn tới nó.
Thay vì {cấu tạo, di chuyển, hủy bỏ}, tôi đề xuất {cấu trúc, hủy, di chuyển}. Động thái, là hành động nguy hiểm nhất, là hành động được thực hiện cuối cùng sau khi mọi việc khác đã được giải quyết.
Có, phá hủy không thành công là một vấn đề trong cả hai chương trình. Dữ liệu bị hỏng (được sao chép khi bạn không nghĩ là có) hoặc bị mất (được giải phóng khi bạn không nghĩ là có). Mất tốt hơn là bị hỏng. Không có dữ liệu nào tốt hơn dữ liệu xấu.
Chuyển khoản thay vì hoán đổi. Đó là gợi ý của tôi anyway.