一、程序的在内存中的存储空间
(1)代码区:存放二进制代码的区域;
(2)文本常量区:a、字符串;b、const全局变量,而const局部变量存放在栈中;
(3)全局变量区(静态变量区):a、data(初始化区):存放已经初始化的的全局变量,static变量;
b、bbs(未初始化区):未初始化的全局变量,static变量,bbs段中数据默认初始化为0;
(4)栈:函数的参数,局部变量,返回值,向下生长;
(5)堆:由程序员控制的内存区域,向上生长。
二、字符串、数组、指针、引用
1、字符串与指针
涉及到strcpy(),memcpy()函数原型的实现。参见:字符串的实现及代码
函数的设计原则下面会具体谈到。
2、数组与指针
静态数组:存放在全局变量区,栈区;而指针可以指向任何区域;运算优先级:[]、->、()、*依次递减。
(1)数组指针 int (*p)[10] 含义:一个指向数组的指针,也被称为行指针
(2)指针数组 int *p[10] 含义:一个存放指针变量的数组
3、二维数组与行指针
例如:
array[4][3]={{1,2,3},{4,5,6},{7,8,9},{10,11,12}};
int * p=array[0];
二维数组array有四个行指针,分别为array[0],array[1],array[2],array[3],每个指针指向一个有3个元素的一维数组,如array[0]的3个元素为 array[0][0],array[0][1],array[0][2]。
元素array[2][2]对应指针为:array+2*3+2,指针表示法为:*(array+2*3+2) , 下标表示法为:array[2*3+2] 。
4、指针与引用
引用的使用要注意:
(1)引用被创建的同时必须被初始化(指针则可以在任何时候被初始化);
(2)不能有NULL引用,引用必须与合法的存储单元关联(指针则可以是NULL);
(3)一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。
三、函数
1、函数与指针
(1)指针函数: int *fun(int , int)
(2)函数指针: int (*fun)(int,int)
函数指针指向某个特定的函数类型,函数类型由其返回值以及形参表决定。
例如:
char (*pFun)(int); char glFun(int a){ return 0;} void main() { pFun = glFun; (*pFun)(2); }
使用typedef
typedef char (*PTRFUN)(int); PTRFUN pFun; char glFun(int a){ return 0;} void main() { pFun = glFun; (*pFun)(2); }
2、函数的设计
(1)函数形参:
const:防止形参改变
指针传递、引用传递、值传递、地址传递
(2)返回值:不能返回栈内存的指针和引用
指针:链式表达式
引用:某些情况下高效
(3)assert宏进行错误判断
四、内存管理
1、管理方式:
(1)全局变量区:data、bbs
(2)栈:静态分配、动态分配
堆:动态分配
2、野指针,free()后的指针,要及时的赋值为NULL;
3、数组:
静态数组:存放在全局变量区,栈区
动态数组:堆区
4、用指针分配内存的方式:
(1)要用二级指针
void GetMemory2(char **p, int num) { *p = (char *)malloc(sizeof(char) * num); } void Test2(void) { char *str = NULL; GetMemory2(&str, 100); // 注意参数是 &str,而不是str strcpy(str, "hello"); cout<< str << endl; free(str); }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
(2)指针函数
char *GetMemory3(int num) { char *p = (char *)malloc(sizeof(char) * num); return p; } void Test3(void) { char *str = NULL; str = GetMemory3(100); strcpy(str, "hello"); cout<< str << endl; free(str); }
五、class、struct
首先要区分出声明、初始化、复制的区别。
1、类的成员:成员函数;成员变量
sizeof一个类,只计算成员变量,而不计算成员函数,所有函数存放在独立于对象的存储空间。
对象调用成员函数时,直接调用静态成员函数,对普通成员函数的调用,需要把自己的this指针传给函数以指明以哪个对象调用;
所以用未初始化的指针调用静态成员函数、或者调用未使用任何成员变量的成员函数(即未用到this指针)
另外,还要注意:
(1)空类大小为1;
(2)如果有虚函数,还要加上虚表指针。
2、访问控制
3、const、static、inline
(1)const除了修饰变量、函数参数、返回值外,在C++中还可以用来修饰函数,称为const成员函数,它表示:常成员函数, 不改变对象的成员变量;在类内定义的成员函数默认是inlin型。
(2)编译阶段进行类型检查。
4、构造函数:
构造函数:a、函数名为类名,
b、可以有参数,也可以无参数,无返回值,
c、函数体可以为空,可以完成对栈、堆得初始化
d、只有给对象分配内存才调用构造函数
(1)初始化列表:
a、如果类存在继承关系,派生类必须在其初始化表里调用基类的构造函数;子对象只能在初始化表里被初始化;
b、类的const常量只能在初始化表里被初始化,因为它不能在函数体内用赋值的方式来初始化;
c、类中的引用成员变量只能在初始化表里被初始化。
类的数据成员的初始化可以采用初始化表或函数体内赋值两种方式,这两种方式的效率不完全相同。
(2)不能为虚函数、不能包含虚函数
(3)可以重载
(4)默认构造函数:无参数、空函数体的构造函数,可以自己定义,也可以是编译系统自动生成的。
在程序中声明一个没有使用初始值的对象时,系统自动调用默认构造函数创建该对象,当该对象为全局变量或static变量时,被初始化为0, 当该对象时局部变量时,值无意义。
(5)拷贝构造函数:
在以下三种情况下都会被自动调用:
a、当用一个类对象去初始化该类的另一个对象时;
b、当函数形参是类的对象,进行实参和形参结合时;
c、当函数返回值为类的对象,函数执行完,返回对象时,调用拷贝构造函数,创建一个临时对象。
默认拷贝构造函数:
如果一个类中没有定义拷贝构造函数,则系统自动生成一个默认拷贝构造函数。
5、析构函数:
(1)可以声明、不能包含虚函数
(2)无形参,无返回值,函数体内完成对象的清理:
A、栈对象,编译器自动清理。在函数执行结束时,自动调用。
B、堆对象,new产生,必须手动清理,通常在析构函数中使用delete实现其析构。
C、全局对象,构造时先调用构造函数,析构时也会调用析构函数,但是程序中看不到调用析构函数。
对类的介绍分为这5个大部分,const、static用法请参考:类的说明
六、继承
1、sizeof
2、访问控制
3、const、static、inline
4、构造函数
5、析构函数
七、多态
1、重载:在同一个类中,要求函数的参数不同,返回值可同可不同,virtual可有可无;
注意与覆盖、隐藏的区别:
覆盖:覆盖是虚函数实现的条件
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual关键字。
隐藏:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数不能有virtual关键字。
或者:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数不同相同;
(4)基类函数可有、可不有virtual关键字。
2、虚函数
1)实现机制
a、类之间满足赋值兼容,public继承
b、声明为虚函数
c、成员函数调用、或者指针和引用访问虚函数
2)纯虚函数、抽象类
包含纯虚函数的类为抽象类,抽象类只能作为基类来派生新类,而不能说明抽象类的对象
详细参考:一个例子说明虚函数
八、模板
模板(Template)是一种强大的C++软件复用特性,通常有两种形式:函数模板和类模板。使用模板的好处在于,可以使程序员编写与类型无关的代码。
函数模板和类模板可以是程序员只需制定一个单独的代码段,就可表示一整套称为函数模板特化的相关(重载)函数或是表示一整套称为类模板特化的相关的类。这种技术称为泛型程序设计(generic programming)。
(1)函数模板针对仅参数类型不同的函数;类模板针对仅数据成员和成员函数类型不同的类。
模板是一个类家族的抽象,它只是对类的描述,编译程序不为类模板(包括成员函数定义)创建程序代码,但是通过对类模板的实例化可以生成一个具体的类以及该具体类的对象。
(2)函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须由程序员在程序中显式地指定。
(3)编译时检查数据类型,保证了类型安全。
注:
static:(限定作用范围)
1、函数内:本函数内使用,值为上次函数内调用的值
2、模块内:本模块内使用,值为上次模块内的值
const:目的:阻止一个变量值改变(限定变量的值改变)
1、只读变量
2、定义时必须初始化
【类外const】
const变量,也称为只读变量,定义时,必须初始化。编译阶段做到只读。C的范畴
const对象, 只读对象,只能调用const型的成员,那么如何对这些成员进行初始化呢,答案是:初始化列表。C++范畴
【类内const】
const成员变量:在类中其实只是声明这个变量为const型,初始化工作在构造函数的初始化列表中进行。
不能再构造函数的函数体里对const变量进行赋值。
const成员函数:只读成员函数,该函数不能修改该对象的成员变量
【const与函数】构造函数、析构函数中不能使用const成员函
const修饰形参,表示这个形参在改函数中不能进行修改。
const修饰返回值,表示这个反回值不能修改。
sizeof:计算一个类型的大小