C++11 中 类实例的初始化问题比较复杂。 这里涉及到实例的类型, (static vs non-static), 有没有自定义构造函数等等。
对于static类型(全局变量,namespace变量,类static数据成员,函数static局部成员),class内部的成员变量都会使用默认值初始化.
//Struct S1 w/o constructor
struct S1 {
string a;
int b;
};
//global S1 object
S1 s1;
//S1 object in anonymous namespace
namespace{ S1 s2; }
//static member of a class
struct S{
static S1 mS;
};
S1 S::mS;
//static local variable of a function
void f()
{
static S1 fs;
cout<<fs.b<<endl;
}
int main() {
cout<<s1.b<<endl; //0
cout<<s2.b<<endl; //0
cout<<S::mS.b<<endl; //0
f(); //0
return 0;
}
对于non-static类型的变量,则如果是自定义类型,会调用默认构造函数,对于非用户自定义类型,则不会初始化。
void f()
{
S1 fs;
cout<<fs.b<<endl; //输出随机数字
}
int main() {
S1 s;
cout<<s.b<<endl; //输出随机数字
f();
return 0;
}
对于non-static类型的变量,如果需要初始化内建类型,可以使用大括号来初始化:
void f()
{
S1 fs {};
cout<<fs.b<<endl; //0
}
int main() {
S1 s {};
cout<<s.b<<endl; //0
f();
return 0;
}
但是对于定义了默认构造函数的类型而言,使用空的大括号相当于调用了默认构造函数,如果用户自定义的默认构造函数没有初始化内建类型的成员变量,那么使用大括号仍然不能初始化内建类型:
//Struct S1 with default constructor
struct S1 {
string a;
int b;
S1() {} //定义默认构造函数
};
void f()
{
S1 fs; //调用默认构造函数
cout<<fs.b<<endl; //输出随机数字
}
int main() {
S1 s {}; //{}调用默认构造函数
cout<<s.b<<endl; // 输出随机数字
f();
return 0;
}
实际上这只是标准对于在这些情形下如何初始化各种类型的成员变量的规定,不同的编译器对于标准的执行会有所不一样,比如对于以上情形,gcc编译器的输出结果都是‘0’,而 VC++编译器的输出和标准也有一些出入,clang的输出则完全符合标准的定义。