原因是,如果该类没有用户定义的构造函数,则它可以是POD,并且默认情况下不会初始化POD类。因此,如果您声明未初始化的POD的const对象,那么它有什么用?因此,我认为标准强制执行此规则,以便该对象实际上是有用的。
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!
但是,如果您将课程设为非POD:
struct nonPOD_A
{
nonPOD_A() {} //this makes non-POD
};
nonPOD_A a1; //initialized
const nonPOD_A a2; //initialized
请注意POD和非POD之间的区别。
用户定义的构造函数是使类成为非POD的一种方法。有几种方法可以做到这一点。
struct nonPOD_B
{
virtual void f() {} //virtual function make it non-POD
};
nonPOD_B b1; //initialized
const nonPOD_B b2; //initialized
注意nonPOD_B没有定义用户定义的构造函数。编译它。它将编译:
并注释虚函数,然后按预期提供错误:
好吧,我想,您误解了这段话。它首先这样说(第8.5 / 9节):
如果没有为一个对象指定初始化程序,并且该对象是(可能是cv限定的)非POD类类型(或其数组),则该对象应被默认初始化;否则,默认为初始化。[...]
它讨论的是非POD类,可能是cv限定类型。也就是说,如果未指定初始化程序,则非POD对象应被默认初始化。什么是默认初始化的?对于非POD,规范指出(第8.5 / 5节),
默认初始化T类型的对象的意思是:
—如果T是非POD类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化格式不正确);
它只是谈论T的默认构造函数,无论它是用户定义的还是编译器生成的都是无关紧要的。
如果您对此有所了解,请了解规范接下来的内容((§8.5/ 9),
[...]; 如果对象是const限定类型,则基础类类型应具有用户声明的默认构造函数。
因此,本文暗示,如果对象为const限定的 POD类型,并且未指定初始化程序,则程序将格式错误(因为POD未默认初始化):
POD p1; //uninitialized - can be useful - hence allowed
const POD p2; //uninitialized - never useful - hence not allowed - error
顺便说一句,因为它不是POD,所以可以很好地编译,并且可以默认初始化。
a
,但gcc-4.3.4甚至在您接受时也接受了该行(请参见ideone.com/uHvFS)