C/C++未初始化的变量
对于基本类型的变量而言,未初始化的变量分为全局变量和局部变量以及静态变量三种情况:
-
全局变量
全局变量在程序装入内存时就已经分配好了内存空间,程序运行期间全局变量的地址不会发生变化。而未初始化的全局变量在内存中会被编译器分配到BSS(Block Started by Symbol)段,未初始化的全局变量和静态变量会被放入BSS段。在程序每次进入运行前之前BSS段会自动清0,所以,未初始的全局变量在程序执行之前已经成0了(这里的0意味着变量的每一位都是0,如4位的int变量,二进制值为"0000",而变量的值为0,又如1位的char变量,其二进制值为’0’,则其变量值为’\0’)。 -
局部变量
局部变量定义在函数内,它的存储空间是动态分配在栈上的,当函数被调用时,栈上会分配一段空间给局部变量,如果没有对局部变量进行初始化,那么这段空间上原本的内容就是局部变量的内容,所以可以认为未初始化的局部变量的值是随机的。 -
静态变量
变量是全局变量还是局部变量取决于变量声明的位置。静态变量并不与局部变量和全局变量并列,程序的任何位置都能够使用static关键字定义静态变量。全局变量在即使没有static关键字修饰,也是默认的静态变量。而局部变量在声明时经过static关键字修饰,可以成为静态变量。未初始化的静态变量同未初始化的全局变量一样,都被编译器分配到BSS区,将其每一位初始化为0。
另外要注意到的是,静态变量的生存期和其标识符的作用域可以不同,忽略这一点可能造成一些认识上的错误,比如,一个静态的局部变量的生存期在整个程序的运行阶段,而其作用域只在该局部内,出了该作用域,即使它还存活,也无法能访问。也就是说,静态修饰符只能修改变量的生存期而不是它的标识符的作用域。
C/C++ 未初始化的对象
同基本数据类型一样,对象也可以分为全局对象和局部对象:
class myClass:
{
public:
int a;
double b;
};
myClass g_mc;
int main()
{
myClass l_mc;
}
以上代码中,g_mc是全局对象,对象中的成员变量也被认为是全局变量进行分配为0;而l_mc中是局部对象,对象中的成员变量也被认为是局部变量为随机值。
构造器进行对象初始化
一个对象的内部结构不像基本数据类型,对象的内部结构可能比较复杂,不仅可能包含基本数据类型,还可能包含其他对象,所以如果不进行初始化可能会产生错误。
因此,C++规定一个对象的生成,一定要通过一个特殊的方式进行初始化,否则不能生成,这个特殊的方式就是构造函数(constructor),往往也可以称之为构造器。
构造函数是特殊的成员函数,在形式上,它没有返回类型、与类同名且可以重载。
C++规定任何对象生成的时,必须要调用构造函数,如上myClass类中没有编写构造函数的情况下,编译器会自动生成一个无参构造器,自动生成的无参构造器什么也不做,只是按照C++的规定在对对象的成员变量初始化时,产生一个入口,再按照基本类型变量的初始化原则进行初始化。一个无参构造器无论是人为编写还是编译器自动生成,都可以认为它是默认构造器,一般只会进行最为原始的初始化行为。
class myClass
{
public:
int a;
//一个人为编写的无参构造器,它由于没有参数,所以无法通过参数为成员变量初始化,但是仍然将其初始化为某个固定的值。
myClass()
{
a = 10;
}
};
其中,能对成员变量赋值的原因在于,构造器的职责并不是为对象分配内存空间,其实每次创建一个对象的时候,成员变量的内存空间已经分配好了,构造器的职责是为这片内存空间进行初始化。
当类中人为编写了任何一个构造器时,编译器则不会自动生成构造器,此时的成员变量的初始化依赖于编写的构造器。另外,构造函数是可以重载的。
构造器的一些高级内容在另外一篇博客中再进行总结。