为什么C ++需要用户提供的默认构造函数来默认构造一个const对象? [英] Why does C++ require a user-provided default constructor to default-construct a const object?
问题描述
C ++标准(第8.5节)说:
The C++ standard (section 8.5) says:
如果程序调用const限定对象的默认初始化类型T,T应为具有用户提供的默认构造函数的类类型。
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
为什么?我不能想到在这种情况下需要用户提供的构造函数的任何原因。
Why? I can't think of any reason why a user-provided constructor is required in this case.
struct B{
B():x(42){}
int doSomeStuff() const{return x;}
int x;
};
struct A{
A(){}//other than "because the standard says so", why is this line required?
B b;//not required for this example, just to illustrate
//how this situation isn't totally useless
};
int main(){
const A a;
}
推荐答案
类没有用户定义的构造函数,那么它可以是POD,并且默认情况下不会初始化POD类。所以如果你声明一个const对象的POD是未初始化的,它的用途是什么?所以我认为标准强制这个规则,以使对象实际上是有用的。
The reason is that if the class doesn't have a user-defined constructor, then it can be POD, and the POD class is not initialized by default. So if you declare a const object of POD which is uninitialized, what use of it? So I think the Standard enforces this rule so that the object can actually be useful.
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:
But if you make the class a non-POD:
struct nonPOD_A
{
nonPOD_A() {} //this makes non-POD
};
nonPOD_A a1; //initialized
const nonPOD_A a2; //initialized
注意POD和非POD之间的区别。
Note the difference between POD and non-POD.
用户定义的构造函数是使类为非POD的一种方法。有几种方法可以做到这一点。
User-defined constructor is one way to make the class non-POD. There are several ways you can do that.
struct nonPOD_B
{
virtual void f() {} //virtual function make it non-POD
};
nonPOD_B b1; //initialized
const nonPOD_B b2; //initialized
注意nonPOD_B没有定义用户定义的构造函数。编译它。它将编译:
Notice nonPOD_B doesn't defined user-defined constructor. Compile it. It will compile:
- http://www.ideone.com/h7TsA
并注释虚拟函数,然后按预期发生错误:
And comment the virtual function, then it gives error, as expected:
- http://www.ideone.com/SWk7B
好吧,我想你误解了这段话。它首先说这个(§8.5/ 9):
Well, I think, you misunderstood the passage. It first says this (§8.5/9):
如果没有为一个对象指定初始值设定项,限定的)非POD类类型(或其数组),对象将被默认初始化; [...]
If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; [...]
它涉及非POD类可能cv限定类型。也就是说,如果没有指定初始化程序,则非POD对象将被默认初始化。什么是默认初始化?对于非POD,规范说(§8.5/ 5),
It talks about non-POD class possibly cv-qualified type. That is, the non-POD object shall be default-initialized if there is no initializer specified. And what is default-initialized? For non-POD, the spec says (§8.5/5),
默认初始化类型T的对象意味着:
- 如果T是非POD类类型(子句9),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化不成功);
To default-initialize an object of type T means:
— if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
它只是谈到T的默认构造函数,无论是用户定义的还是编译器生成的都是不相关的。
It simply talks about default constructor of T, whether its user-defined or compiler-generated is irrelevant.
如果你清楚了解这一点,那么请明白规范接下来说的是什么((8.5 / 9),
If you're clear up to this, then understand what the spec next says ((§8.5/9),
[...];如果对象是const限定类型,底层类类型应该有一个用户声明的默认构造函数。
[...]; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor.
因此,这段文字暗示,程序将是不成形的如果对象是 const限定 POD类型,并且没有初始化(因为POD不是默认初始化的):
So this text implies, the program will be ill-formed if the object is of const-qualified POD type, and there is no initializer specified (because POD are not default initialized):
POD p1; //uninitialized - can be useful - hence allowed
const POD p2; //uninitialized - never useful - hence not allowed - error
顺便说一下,此编译精细,因为它的非POD,并且可以默认初始化。
By the way, this compiles fine, because its non-POD, and can be default-initialized.
这篇关于为什么C ++需要用户提供的默认构造函数来默认构造一个const对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!