默认初始化
这是在没有初始化程序的情况下构造变量时执行的初始化。
句法
T 对象 ; |
(1) | ||||||||
new Ť
|
(2) | ||||||||
说明
默认初始化在以下三种情况下执行:
1)在没有初始化程序的情况下声明了具有自动,静态或线程本地存储持续时间的变量时;
2)当具有动态存储持续时间的对象是由没有初始化程序的new表达式创建的,或者是由带有空括号对的初始化程序的new表达式创建的对象时 (直到C ++ 03);
3)当构造函数初始化器列表中未提及基类或非静态数据成员时,将调用该构造函数。
默认初始化的效果是:
- 如果
T
是一个非POD (直到C ++ 11)类型,构造函数被认为是,进行重载解析靠在空参数列表。调用选定的构造函数(这是默认的构造函数之一)来为新对象提供初始值; - 如果
T
是数组类型,则数组的每个元素都将默认初始化; - 否则,什么也不做:具有自动存储持续时间的对象(及其子对象)被初始化为不确定的值。
当不使用初始化程序时,只有具有自动存储持续时间的(可能是cv限定的)非POD类类型(或其数组)才被视为默认初始化。具有动态存储持续时间的标量和POD类型被认为未初始化(从C ++ 11开始,这种情况被重新分类为默认初始化的形式)。 |
(直到C ++ 11) |
在C ++ 03(引入了值初始化)之前,表达式新的T ()以及以空括号对的形式命名基址的成员初始化程序或使用初始化程序命名成员的成员初始化程序被分类为默认初始化,但对非类类型指定为零初始化。 |
(直到C ++ 03) |
如果 |
(直到C ++ 11) |
从不确定的字节读取
通过缺省初始化任何类型的非类变量而获得的不确定值的使用是未定义的行为(特别是,它可能是陷阱表示),但在以下情况下除外:
- 如果类型的不确定值 未签名的 字符 或std :: byte (自C ++ 17起)被分配给另一个类型的变量(可能是cv限定的)未签名的 字符 或std :: byte (自C ++ 17起)(变量的值不确定,但行为未定义);
- 如果类型的不确定值 未签名的 字符 或std :: byte (因为C ++ 17)用于初始化另一个类型的变量(可能是cv限定的)未签名的 字符 或std :: byte (C ++ 17起) ;
- 如果类型的不确定值 未签名的 字符 或std :: byte (C ++ 17起)的结果是
-
- 条件表达式的第二或第三操作数,
- 逗号运算符的正确操作数,
- 强制转换或转换为(可能是cv限定)的操作数 未签名的 字符 或std :: byte (C ++ 17起),
- 舍弃值表达式。
int f (bool b )
{
int x ; // OK:x的值不确定
int y = x ; //未定义行为
unsigned char c ; // OK:c的值是不确定的
无符号 char d = c ; // OK:d的值是不确定的
int e = d ; //未定义行为
return b吗?d : 0 ; //如果b为true,则为未定义的行为
}
笔记
具有自动和动态存储持续时间的非类变量的默认初始化会产生具有不确定值的对象(静态和线程本地对象初始化为零)。
如果T
是const限定类型,则它必须是具有用户提供的默认构造函数的类类型。
引用无法默认初始化。
例
运行此代码
#include <string>
结构T1 { int mem ; } ;
结构T2
{
int mem ;
T2 () { } //“内存”不在初始化列表中
} ;
int n ; //静态非类,完成了两阶段初始化:
// 1)零初始化将n初始化为零
// 2)默认初始化不执行任何操作,而n为零
int main ()
{
int n ; //非类,值不确定
std :: string s ; //类,调用默认的ctor,值是“”(空字符串)
std :: string a [ 2 ] ; //数组,默认初始化元素,值是{“”,“”}
// int&r; //错误:一个引用
// const int n; //错误:const非类
// const T1 t1; //错误:具有隐式默认值ctor
T1 t1的const类; //类,调用隐式默认ctor
const T2 t2 ; // const类,调用用户提供的默认ctor
// // t2.mem是默认初始化的(不确定的值)
}
缺陷报告
以下行为更改缺陷报告已追溯应用于以前发布的C ++标准。
博士 | 应用于 | 行为已发布 | 正确行为 |
---|---|---|---|
CWG 616 | C ++ 98 | 任何未初始化对象的左值到右值转换始终是UB | 不定 未签名的 字符 被允许 |
CWG 1787 | C ++ 98 | 读不确定 未签名的 字符 缓存在寄存器中的是UB | 定义明确 |