Lý do là nếu lớp không có hàm tạo do người dùng định nghĩa thì nó có thể là POD và lớp POD không được khởi tạo theo mặc định. Vì vậy, nếu bạn khai báo một đối tượng const của POD chưa được khởi tạo, thì việc sử dụng nó là gì? Vì vậy, tôi nghĩ Tiêu chuẩn thực thi quy tắc này để đối tượng có thể thực sự hữu ích.
struct POD
{
int i;
};
POD p1; //uninitialized - but don't worry we can assign some value later on!
p1.i = 10; //assign some value later on!
POD p2 = POD(); //initialized
const POD p3 = POD(); //initialized
const POD p4; //uninitialized - error - as we cannot change it later on!
Nhưng nếu bạn đặt lớp này thành không phải POD:
struct nonPOD_A
{
nonPOD_A() {} //this makes non-POD
};
nonPOD_A a1; //initialized
const nonPOD_A a2; //initialized
Lưu ý sự khác biệt giữa POD và không phải POD.
Hàm tạo do người dùng định nghĩa là một cách để làm cho lớp không phải là POD. Có một số cách bạn có thể làm điều đó.
struct nonPOD_B
{
virtual void f() {} //virtual function make it non-POD
};
nonPOD_B b1; //initialized
const nonPOD_B b2; //initialized
Lưu ý rằng nonPOD_B không xác định hàm tạo do người dùng xác định. Biên dịch nó. Nó sẽ biên dịch:
Và nhận xét hàm ảo, sau đó nó báo lỗi, như mong đợi:
Tôi nghĩ bạn đã hiểu sai đoạn văn. Đầu tiên nó nói điều này (§8.5 / 9):
Nếu không có trình khởi tạo nào được chỉ định cho một đối tượng và đối tượng thuộc loại lớp không POD (có thể đủ điều kiện cv) (hoặc mảng của nó), đối tượng sẽ được khởi tạo mặc định; [...]
Nó nói về lớp không phải POD có thể là loại cv đủ tiêu chuẩn . Tức là, đối tượng không phải POD sẽ được khởi tạo mặc định nếu không có bộ khởi tạo nào được chỉ định. Và mặc định khởi tạo là gì? Đối với không phải POD, thông số cho biết (§8.5 / 5),
Để khởi tạo mặc định một đối tượng kiểu T có nghĩa là:
- nếu T là kiểu lớp không phải POD (điều 9), hàm tạo mặc định cho T được gọi (và quá trình khởi tạo không hợp lệ nếu T không có hàm tạo mặc định có thể truy cập);
Nó chỉ đơn giản nói về phương thức khởi tạo mặc định của T, cho dù nó do người dùng định nghĩa hay do trình biên dịch tạo ra đều không liên quan.
Nếu bạn hiểu rõ điều này, thì hãy hiểu thông số tiếp theo nói gì ((§8.5 / 9),
[...]; nếu đối tượng thuộc kiểu đủ điều kiện const, thì kiểu lớp bên dưới sẽ có một hàm tạo mặc định do người dùng khai báo.
Vì vậy, văn bản này ngụ ý, chương trình sẽ bị lỗi nếu đối tượng thuộc loại POD đủ điều kiện const và không có bộ khởi tạo nào được chỉ định (vì POD không được khởi tạo mặc định):
POD p1; //uninitialized - can be useful - hence allowed
const POD p2; //uninitialized - never useful - hence not allowed - error
Nhân tiện, điều này biên dịch tốt , vì nó không phải POD và có thể được khởi tạo mặc định .
a
, nhưng gcc-4.3.4 chấp nhận nó ngay cả khi bạn làm vậy (xem ideone.com/uHvFS )