1 变量的初始化
1.1变量的初始化方式
C++支持两种形式的变量初始化:复制初始化和直接初始化。复制初始化的语法符号用等号(=),直接初始化的语法符号是用括号把初始化的值括起来:
int ival = 1024;//复制初始化
int ival(1024); //直接初始化
注意: C++中初始化不是赋值!初始化指创建变量并给他赋初值,而赋值则是指擦出对象的当前值并用新值代替。
直接初始化语法更灵活且效率更高。
1.2内置类型变量的初始化
内置类型的变量是否自动初始化取决与变量定义的位置,在函数体外定义的变量都会被自动初始化为0,在函数体内定义的变量则不进行自动初始化。
注意: 静态变量若没有初始化,则不管是它在函数体内还是体外,都初始化为0。
- 普通变量:
- 初始化的普通全局变量放在目标文件的.data区,该类型变量的初始值因为在代码中已经给出了,所以该值最后也会保存在目标文件(存放在磁盘上的文件)的.data区中;
- 未初始化的普通全局变量放在.bss区,该类型的变量因为没有初始值,因此在目标文件中没有存放该变量的初始值,而是在目标文件加载到内存中的时候会自动赋初值0;
- 函数体内的普通变量不在目标文件中,因为函数体内的变量是在函数调用时在内存的函数栈帧中分配的空间,且不会自动赋初值。
- 静态变量:
- 初始化的全局静态变量放在目标文件的.data区,其初始值就存在.data中。
- 未初始化的静态全局静态变量放在.bss区,其没有初始值,而是在目标文件加载到内存中的时候,系统自动赋初值0;
- 函数体类的静态变量,这是特殊情况,和函数体内的普通变量不一样,该变量会存放在目标文件的.data或者.bss区中,如果在函数体内已经初始化了,就放在.data区中,若没有则放在.bss中。
1.3变量的定义与声明
- 变量的定义
- 用于为变量分配存储空间,还可以为变量指定初始值。
变量的声明
- 用户向程序标明变量的类型和名字,通过extern关键字来声明变量。
注意:定义也是声明,但声明不是定义!
例如
int a;//是变量的定义,同时也是变量的声明
int a = 1;//变量的定义,并复制初始化,当然也是变量的声明
int a(1);//变量的定义,并直接初始化,当然也是变量的声明
extern int a;//只是变量的声明
extern int a = 1;//是变量的定义,因为赋值要分配空间所以是定义,当然也是声明;
extern int a(1);//变量的定义,并直接初始化
2 头文件
2.1 头文件中内容
头文件中一般包含的是变量和函数的声明;而不是用于定义,但有三个例外。
- 头文件中可以定义类
- 在一个给定的源文件中,一个类只能定义一次,如果在多个文件中定义一个类,那么每个文件中的类定义必须完全相同,而且都只能出现一次,所以将类的定义放在头文件中可以保证这点
- 值在编译时候就知道的const对象
- inline函数
- 同类的定义一样,所有源文件中,其定义必须要完全相同。
2.2 避免多重包含
源文件A中包含了string头文件,也包含的B头文件,但B中也包含了string头文件,这样string头文件在A中就包含了2次。(没问题,编译通过,也能正常运行,只要不出现下面粗体字的问题即可)
因此在设计头文件的时候,应该使其可以多次包含在同一源文件中,这点很重要,我们必须保证多次包含同一头文件不会引起该头文件定义的类和对象被多次定义。 使用头文件保护符可以避免在已经见到头文件的情况下重新处理该头文件的内容。
#ifndef XXX_H
#define XXX_H
头文件中的类容
#endif
3 指针和const限定符
3.1 指向const对象的指针
const int *p;
int const *p;
- const对象的地址只能赋给指向const对象的指针,不能赋给指向非const对象的指针。
- 允许把非const对象的地址赋给指向const对象的指针,但不能通过该指针来修改指向的非const对象的值。
3.2 const指针
int *const p;
- 该指针的值不能变,和const变量一样,是常量了。
- 但该指针指向的对象的值可以变。
3.3 指向const对象的const指针
const int *const p;
int const *const p;
3.4 指针与typedef
typedef string *p;
const p sp;
理解为 const string * sp;即sp是指向const string对象的指针是错的!
应该为sp 是指向string对象的const指针;
因为const p时候,p表示string * 是一个指针,即const修饰的是一个指针,代表一个const指针,所以sp为指向string对象的const指针
这个地方比较特殊,源于const限定符在类型前和类型后的位置,一般这种typedef定义容易误导人,最后从右向左读。
4 new与delete
new操作是返回一个指针!
未提供默认构造函数的对象在new的时候必须显示的初始化
普通变量和对象
new操作
int *pi = new int;//分配一个整形,未初始化
int *pi = new int();//分配一个整形,初始化为0
int *pi = new int(1024);
string *ps = new string; == new string();//分配一个string对象空间,初始化为空,调用的是string类的默认构造函数,注意与普通变量的区别
string *ps = new string(参数);//分配一个string对象空间,调用string类相应的构造函数
const int *pci = new const int(数字);//分配一个const int对象空间,并初始化delete操作
delete pi; delete ps; delete pci;
动态数组
new操作
int *pia = new int[10];//申请10个int元素的数组,元素值未知 int *pia = new int[10]();//申请10个int元素的数组,并元素值都初始化为0 int *pia = new int[10](6);//error string *psa = new string[10];//申请10个string元素的数组,并元素值都初始化为空 //分配一个二维数组,大小不定 int **pia2 = new int *[10];//申请10个int *元素的数组,元素值未知; for(...){ pia2[i] = new int[x](); } //为指向const类型的指针非配空间 const int *pcia = new const int[10];//error const int *pcia = new const int[10]();//必须初始化
delete操作
//一维数组的delete delete [] pia; delete [] psa; //二维数组的delete for(...){ delete pia2[i]; } delete [] pia2; //const对象的一维数组的delete delete pcia;
注意:
1. new后,一定要判断是否分配成功
2. new后空间,一定要用delete释放;
3. delete后的指针变量,一定要注意悬垂指针问题,即野指针!
5 指针和多维数组
5.1 多维数组
严格的说c++中没有多维数组,通常多维数组是指数组的数组。
- 与普通数组一样,使用多维数组名时,实际上将其自动转换为指向该数组第一个元素的指针。
- 二维数组(数组的数组)的第一个元素是一个一维数组。
- 指向一维数组的指针: int (*p)[10];//p是指向一个包含10个int元素的一维数组的指针。
因此函数中形参为多维数组时,形参的定义为:
void fun(int a[][10],...); <==> void fun(int (*a)[10],...);
若不确定二维数组的大小,可以用二维指针形式,即到时候可以动态分配空间;
void fun(int **a,...){
a = new int *[数字1];//new返回的是指针,
if(a ==