内存分配方式有哪些?
C语言内存分配方式:
1) 从静态数据区分配,该内存在程序编译的时候就已经分配好,直到程序运行结束。分为BSS、Data、Rodata段,BSS存放未初始化的全局变量,Rodata存放常量,data存放初始化的全局变量和静态变量。
2) 从堆上分配,动态内存分配,程序运行时用new,malloc分配的空间,声明周期由用户决定,free/delete。向上增长。
3) 从栈上分配,在执行函数时,函数内的局部变量的存储单元可以在栈上创建,函数运行结束后内存释放,这段内存执行效率高,容量有限。向下增长。
什么是内存泄漏?
内存泄漏:访问已经释放的内存;访问没有权限的内存。
常发性内存泄漏:发生内存泄漏的代码被多次执行到,每次执行都会造成一块内存泄漏;
偶发性内存泄漏:发生内存泄漏的代码只有在特定的环境下或操作过程下才发生;
一次性内存泄漏:发生内存泄漏的代码只执行一次,或者由于算法的取消,导致总有一块且只有一块内存泄漏。
隐藏性内存泄漏:在程序运行过程中不断地分配内存,到程序运行结束后才释放内存,严格来说没有发生内存泄漏,但长时间运行之后才结束就回造成所有内存耗尽。
什么是野指针?如何避免野指针?
什么是野指针:
1) 指针变量没有初始化;
2) 指针free后没有置为NULL;
3) 指针操作超越变量的作用范围。
如何避免?
1) 对指针进行初始化:将指针初始化为NULL;用malloc分配内存;用已有合法的可访问的内存地址初始化
2) 指针用完后释放,并置为NULL,用malloc分配内存的步骤:
a) malloc分配内存(分配成功,返回内存首地址,失败返回NULL)
b) 判断内存是否分配成功(失败,exit(1),退出程序)
c) 清空内存数据(memset\bzero)
d) 使用内存
e) 释放内存
f) 置为NULL
什么时候将引用作为返回值
1) 将引用作为返回值,在内存中不产生被返回值的副本,提高程序的安全性和效率。
2) 不能返回局部变量的引用
3) 不能返回函数内部new分配的内存引用
4) 返回类成员的引用,最好是常引用。
5) 流操作符<<、>>返回引用
6) 不能返回引用的是+-*/,应该返回对象。
引用与指针的区别
1) 引用访问一个变量是直接访问,指针是简介访问;
2) 指针是存放变量地址的一个变量,在逻辑上是独立的,它可以改变,指向的地址也可以改变;引用只是一个别名,在逻辑上是不独立的,一旦初始化,它引用的对象在整个生命周期不能改变。
3) 引用只是一个别名,本身不单独分配内存空间,指针有自己的内存空间。
4) 引用在定义时就必须初始化,指针可以不初始化。
5) 引用经初始化后就不能引用其他变量,指针可以。
6) sizeof求指针大小时是固定的值(32位系统下为4),而引用的值不固定,其大小是所引用对象的大小。
7) 引用不可以为空,指针可以。
8) 引用使用时不需要解引用,指针需要。
9) 指针和引用的自增运算意义不同。
10) 返回动态分配的对象或内存时,必须使用指针,使用引用可能造成内存泄漏。
数组与指针的区别
1) 数组和指针的定义与声明是不同的,定义是数组时,声明也应该是数组。
2) 数组可以在静态存储区或栈上被创建,数组名对应一块内存,其地址和容量在生命期内保持不变,只有数组内容可以改变;但是指针可以随时指向任意类型的内存块,可以改变,指针比数组灵活,但也比数组危险。
3) 当用下标操作符对数组和指针进行运算时,数组和指针是等价的,a[i]编译器会翻译成*(a+i).
4) 当数组名作为函数形参时,数组实际会当做指针来使用。
5) 修改内容不同,数组可以通过下标对数组内容进行修改,但一个指向常量字符串的指针,不能进行修改。
6) 内容复制与比较。不能对数组名直接进行复制和比较,要用strcpy、strcmp函数
7) 计算内存容量,对数组求sizeof可以获得数组的容量,但是对指针求sizeof只能得到固定的指针变量的字节数。
函数指针与指针函数的区别
1) 函数指针,其本质是一个指针变量,该指针指向一个函数,一般形式为:type (*指针变量名)(形参表);
2) 指针函数,其本质是一个函数,返回值为一个指向函数的指针变量,一般形式为:type *函数名(形参表);
数组指针与指针数组的区别
1) 数组指针,其本质是一个指针变量,指针指向一个数组,一般形式为:type (*指针变量名)[10];
2) 指针数组,其本质是一个数组,数组元素是指针,一般形式为:type *数组名[10];
指针常量与常量指针的区别
1) 指针常量是指指针指向不能改变(const在*右边)
2) 常量指针是指指针指向的变量是常量,其值不能通过指针来改变(const 在*左边)
函数模板与模板函数的区别
1) 函数模板是对一批模样相同的函数的说明描述,不是一个具体的函数,是抽象的。
2) 模板函数是将函数模板中的数据类型参数具体化的重载函数,是具体的。
类模板与模板类的区别
1) 类模板是代码类似的类的集合,是类的抽象
2) 模板类是具体化后的来模板,是具体的。
引入类模板的好处
1) 可以用来创建动态增长或减小的数据结构
2) 类型无关,具有很高的复用性
3) 在编译时而不是运行时检查数据类型,保证类型安全
4) 平台无关,可移植性强
5) 可用于基本数据类型
重载overload、覆盖overwrite、隐藏override的区别
1) 重载的条件:相同的范围(同一个类中);函数名相同;参数列表不同;virtual可有可无
2) 覆盖的条件:不同的范围(派生类、基类);函数名相同、参数列表相同;必须有virtual
3) 隐藏的条件:不同的范围(派生类、基类);函数名相同;参数列表可同可不同,相同时,virtual可有可无,区别于重载(范围是否相同),不同时,没有virtual(区别于覆盖)
4) 覆盖根据对象的类型选择方法体,重载根据参数列表选择方法体