class A {};
int main() {
A() = A();
return 0;
}
Tại sao mã này biên dịch? Sẽ không có một số lỗi mà ở phía bên trái của toán tử gán phải được đặt giá trị? A () có phải là giá trị không? g ++ phiên bản 4.7
Câu trả lời:
Đối với các loại tích hợp, bạn đã đúng: toán tử gán tích hợp yêu cầu giá trị có thể sửa đổi ở phía bên trái.
Tuy nhiên, đây không phải là sử dụng toán tử tích hợp, mà là quá tải được khai báo ngầm bởi lớp. Đây là một chức năng thành viên, tương đương với
A().operator=(A());
và các hàm thành viên có thể được gọi trên các giá trị .
operator=không operator()), nhưng không liên quan nhiều đến câu hỏi. Ví dụ không làm bất cứ điều gì với kết quả của bài tập.
A()không gọi operator(), nó xây dựng một đối tượng kiểu A.
Nếu bạn thực sự muốn, bạn có thể làm cho nó không biên dịch bằng C ++ 11:
class A {
template <typename T>
void operator=(T&&) && = delete; // no op= for rvalues
// generate other special members normally
A() = default;
A(A const&) = default;
A(A&&) = default;
~A() = default;
// op= only for lvalues
A& operator=(A&&) & = default;
A& operator=(A const&) & = default;
};
int main() {
A() = A(); // error
return 0;
}
( ví dụ trực tiếp )
Lưu ý &và &&(hay còn gọi là vòng loại tham chiếu) ở cuối khai báo của các operator=biểu mẫu khác nhau . Điều này làm cho các khai báo đó được chọn cho các giá trị và giá trị tương ứng. Tuy nhiên, phiên bản rvalue, khi được chọn theo độ phân giải quá tải sẽ khiến chương trình bị lỗi do nó bị xóa.
Tuy nhiên, toán tử được tạo mặc định = không có bất kỳ định nghĩa ref nào, có nghĩa là nó có thể được gọi cho cả giá trị và giá trị r; đó là lý do tại sao mã trong câu hỏi được biên dịch, mặc dù A()là một giá trị.
Trình biên dịch C ++ cung cấp cho tất cả các lớp một hàm tạo mặc định, đó là điều đang xảy ra, đối với mã của bạn, khi bạn nói A () = A (); nó chỉ gọi phương thức khởi tạo với một đối tượng không tên và hàm trả về tham chiếu đến đối tượng được xây dựng (ngầm định). Đó là nó...