Angew của và jaggedSpire của câu trả lời là tuyệt vời và áp dụng đối vớic ++ 11. Vàc ++ 14. Vàc ++ 17.
Tuy nhiên, trong c ++ 20, mọi thứ thay đổi một chút và ví dụ trong OP sẽ không biên dịch nữa:
class C {
C() = default;
};
C p; // always error
auto q = C(); // always error
C r{}; // ok on C++11 thru C++17, error on C++20
auto s = C{}; // ok on C++11 thru C++17, error on C++20
Như đã chỉ ra bởi hai câu trả lời, lý do hai khai báo sau hoạt động là vì C
là một tập hợp và đây là sự khởi tạo tổng hợp. Tuy nhiên, theo kết quả của P1008 (sử dụng một ví dụ thúc đẩy không quá khác với OP), định nghĩa về tổng hợp thay đổi trong C ++ 20 thành, từ [dcl.init.aggr] / 1 :
Tổng hợp là một mảng hoặc một lớp ([class]) với
- không có hàm tạo do người dùng khai báo hoặc kế thừa ([class.ctor]),
- không có thành viên dữ liệu tĩnh không tĩnh trực tiếp hoặc riêng tư hoặc được bảo vệ ([class.access]),
- không có chức năng ảo ([class.virtual]) và
- không có lớp cơ sở ảo, riêng tư hoặc được bảo vệ ([class.mi]).
Nhấn mạnh của tôi. Bây giờ yêu cầu là không sử dụng tuyên bố nhà thầu, trong khi nó được sử dụng để được (như cả người dùng trích dẫn trong câu trả lời của họ và có thể xem lịch sử cho C ++ 11 , C ++ 14 , và C ++ 17 ) không dùng cung cấp nhà xây dựng . Hàm tạo mặc định cho C
là do người dùng khai báo, nhưng không do người dùng cung cấp và do đó không còn là tổng hợp trong C ++ 20.
Đây là một ví dụ minh họa khác về các thay đổi tổng hợp:
class A { protected: A() { }; };
struct B : A { B() = default; };
auto x = B{};
B
không phải là tổng hợp trong C ++ 11 hoặc C ++ 14 vì nó có một lớp cơ sở. Do đó, B{}
chỉ cần gọi hàm tạo mặc định (do người dùng khai báo nhưng không do người dùng cung cấp), có quyền truy cập vào hàm tạo A
mặc định được bảo vệ của.
Trong C ++ 17, là kết quả của P0017 , các tổng hợp được mở rộng để cho phép các lớp cơ sở. B
là một tổng hợp trong C ++ 17, có nghĩa B{}
là khởi tạo tổng hợp phải khởi tạo tất cả các subobject - bao gồm cả A
subobject. Nhưng bởi vì hàm tạo A
mặc định của được bảo vệ, chúng tôi không có quyền truy cập vào nó, do đó, quá trình khởi tạo này không được hình thành.
Trong C ++ 20, vì hàm tạo do B
người dùng khai báo, nó một lần nữa không còn là một tập hợp, do đó, B{}
trở lại gọi hàm tạo mặc định và điều này lại được khởi tạo đúng cách.
C c{};
khởi tạo tổng hợp để không có hàm tạo nào được gọi?