动态内存分配
普通变量的动态内存分配
C++ 程序的内存分为两部分
- <b>栈:</b>在函数内部声明的所有变量都将占用栈内存。
- <b>堆:</b>这是程序中未使用的内存,在程序运行时可用于动态分配内存。
而 new 关键字就是 C++ 用于动态内存分配的。
#include<iostream>
using namespace std;
int main(){
double *d = nullptr;
d = new double;
*d = 123;
cout<<*d<<endl; // 123
}
数组的动态内存分配
使用 new 关键字为一维数组分配内存
#include<iostream>
using namespace std;
int main(){
int *arr = nullptr;
arr = new int[10];
*(arr) = 1;
*(arr+1) = 2;
// 直接用数组形式的下标范围
cout<<arr[0]<<endl;
// 计算指针偏移量也可以
cout<<*(arr)<<endl;
cout<<*(arr+1)<<endl;
}
使用 new 关键字为二维数组分配内存
#include<iostream>
using namespace std;
int main(){
int **array;
array = new int*[10];
for(int i=0; i<10; i++){
array[i] = new int[10];
}
// 二维数组范围。先拿到一维数组的地址,再加上偏移量。
// 最后从地址中拿数据
cout<<*(array[0]+0)<<endl;
cout<<*(array[0]+1)<<endl;
}
内存释放
普通变量直接 delete 变量名。数组稍微特殊点。
int main(){
int **array;
array = new int*[10];
for(int i=0; i<10; i++){
array[i] = new int[10];
}
// 二维数组先释放一维数组,再释放二维数组。
for (int i = 0; i < 10; i++){
delete []array[i];
}
delete []array;
// cout<<*(array[0]+0)<<endl;
// cout<<*(array[0]+1)<<endl;
}
函数模板
函数模板是函数的抽象,它与普通函数相似,唯一的区别就是函数参数的类型是不确定的,函数参数的类型只有在调用过程中才被确定。
template<typename 占位符, typename 占位符> 返回值类型 函数名(参数列表){
// 函数体
}
定义一个适用于 int、double、float 的 add 运算函数。
#include<iostream>
using namespace std;
template<typename T> T add(T one, T two){
return one+two;
}
int main(){
cout<<add(1,1)<<endl;
cout<<add(1.1,1.2)<<endl;
}
函数模板并不是一个函数,它相当于一个模子,定义一次即可使用不同类型的参数来调用该函数模板,这样做可以减少代码的书写,提高代码的复用性和效率。需要注意的是,函数模板不会减少可执行程序的大小,因为编译器会根据调用时的参数类型进行相应的实例化。所谓实例化,就是用类型参数替换模板中的模板参数,生成具体类型的函数。<b>实例化可分为隐式实例化与显式实例化。</b>
隐式实例化
隐式实例化是根据函数调用时传入的参数的数据类型确定模板参数 T 的类型,模板参数的类型是隐式确定的。比如调用 add(1,1) 会根据模板实例化出一个 int 类型的函数:
int add(int t1,int t2) {
return t1 + t2;
}
每一次调用时都会根据不同的类型实例化出不同类型的函数,最终的可执行程序的大小并不会减少,只是提高了代码的复用性。
显示实例化
显示实例化就是显示的创建一个模板的实例。
#include<iostream>
using namespace std;
template<typename T> T add(T one, T two){
return one+two;
}
// 可以省略。
template int add(int t1, int t2);
int main(){
// 调用显示实例化的模板实例
cout<<add<int>(1,1)<<endl;
cout<<add(1.1,1.2)<<endl;
}
类模板
template <typename type> ret-type func-name(parameter list){}
template <typename type, typename tyep> ret-type func-name(parameter list){}
定义一个基于模板的含有两个元素的元组。
#include<iostream>
using namespace std;
template<class T1,class T2> class Tuple{
public:
T1 element1;
T2 element2;
Tuple(T1 t1,T2 t2);
T1 sum(T1 t1, T2 t2);
};
// 构造方法
template<class T1, class T2> Tuple<T1, T2>::Tuple(T1 t1, T2 t2){
this->element1 = t1;
this->element2 = t2;
}
// 元组元素求和
template<class T1,class T2> T1 Tuple<T1,T2>::sum(T1 t1, T2 t2){
return t1+t2;
}
int main(){
Tuple<int,double> *t = new Tuple<int,double>(10,11.2);
cout<<t->sum(1,2)<<endl; // 3
cout<<t->element1<<endl; // 10
cout<<t->element2<<endl; // 11.2
}