相较于别的高级语言,C/C++最大的特点就是它将内存管理的权力交给了程序员自身,从而使得程序员可以高效的操作内存,这是说C/C++更加接近底层的原因之一,但是与此同时伴随而来的也有一些弊端,如一些程序员没有在申请空间后即使释放所申请的空间,称之为内存泄漏(即内存中一部分空间始终被无用数据所占据),内存泄漏一般在初期和一些小型程序中不易被发现,但是在一些永不停歇的大型项目下内存泄漏会使得内存空间的可利用空间不断缩小,减慢运行速度,故而要防止内存泄漏必须要在编写时就要注意及时释放,(这是一个平时编写代码时的优良习惯)。
内存结构大致可以分为堆区、栈区、未初始化变量,已初始化变量、字符常量、代码段区域,具体解释见下图
图示:
C环境下当我们要动态开辟or释放空间,通常会调用库函数malloc和free,C++中新设立了new和delete关键字来帮助我们更快捷地实现空间开辟和释放,具体操作如下
int* ptr1=new int;
//开辟一块int类型大小的空间
int* ptr2=new int[3];
//开辟三块连续的int类型大小的空间
int* ptr3=new int(1);
//开辟一块int类型大小的空间并初始化为1
int* ptr4=new int[3]{1,2};
//开辟三块连续的int类型大小的空间并依次初始化为1,2,0
delete ptr1;
delete ptr3;
//释放单独一块空间
delete[] ptr2;
delete[] ptr4;
//释放一块连续的空间
显然new和delete的方法在写法上变得更为简洁,但这不是它们与malloc、free的本质区别
它们的本质区别是new和delete在申请自定义类型空间时会自动调用该类对象的构造函数和析构函数来实现初始化和销毁。
以顺序表对象为例子图解:
class SeqList{
public:
SeqList(){
int* _a=new int[10];
}
~SeqList(){
delete[] _a;
_a=nullptr;
}
private:
int* _a=nullptr;
int _size=0;
int _capacity=0;
};
补充:
1、我们在动态内存管理的时候一定注意关键字或函数的搭配使用,
malloc搭配free
new搭配delete
new[]搭配delete[]
不能混淆使用
2、new申请空间失败时会抛出异常,而malloc返回空指针
尽管C++中引入了函数重载的方法减少了函数冲突的问题,但是如果一个重载函数有很多目的,那么我们需要编写很多次,这样显得非常麻烦,于是就想着把这些函数视作一个集合,打包成一个模板,在传参时编译器自动识别参数类型并形成相应参数类型的函数
模板的用法
template<typename T>
T Add(T arg1,T arg2){
return agr1+arg2;
}//函数模板
template<typename T>
class SeqList{
private:
T* _a=nullptr;
//......
}; //类模板
Add(1,2);//编译器生成int型的Add函数
Add(1,2.0);//error,编译器无法判断,模板不支持隐式类型转化
Add(2.0,3.0);//编译器生成double型的Add函数
Add<int>(1,2.0);//告诉编译器生成Add函数,参数强制转为int类型