A () = A () - tại sao nó biên dịch?


85
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:


88

Đố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ị .


7
nó không phải là sao chép khởi tạo?
stardust

13
@Named: Không, đó là nhiệm vụ không phải là khởi tạo.
Mike Seymour,

1
@ paul23: Đúng vậy (giả sử ý bạn là 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.
Mike Seymour,

3
@ paul23 A()không gọi operator(), nó xây dựng một đối tượng kiểu A.
tục

3
Nó không thể là một khởi tạo vì không có khai báo.
Kos,

32

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 ý &&&(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ị.


1

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ó...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.