https://blog.csdn.net/Errors_In_Life/article/details/78889951
https://blog.csdn.net/a573233077/article/details/50518909
https://blog.csdn.net/weiwenhp/article/details/8006587
数组是最常用的一种数据结构,其缺点是使用时必须确定数组大小,因此会带来一些不便:
1)需要保存的数据大小不确定时,预先开辟的空间太小装不下,太大则浪费空间;
2)使用的数据大部分默认保存在栈(stack)里,由系统管理,自动分配,自动删除。但是stack很小,如果读取的数据很大的话容易溢出。
3)系统要等到变量周期结束时才会释放内存,当内存比较紧缺时,没法立即释放。
4)动态分配的优点:根据函数调用的需要,动态地分配和释放存储空间,大大提高了内存的使用效率。
1)C语言使用标准库函数malloc()和free()来实现动态分配。
2)void *malloc(int size):申请size个字节空间,返回值是void *(未确定类型的指针,即在申请内存时用户还不知道要用来存储什么类型的数据,C/C++规定void *类型可以强制转换为任意类型),所以需要做强制类型转换为int*指针。
3)malloc的参数是内存大小,以字节为单位,表示要申请多少个字节。而在不同的系统里面int类型占用的字节不一样,而且malloc所以首先需要使用sizeof计算。
4)malloc只能分配内存,不能对所得的内存进行初始化,所以其初值为随机的。
5)注意事项:申请内存空间后必须检查是否分配成功,用完释放,使原来指向该内存的指针指向NULL,防止后面程序不小心使用了它。
6)C程序只能用malloc/free管理动态内存;
1)C++里的类class里面的构造函数是在类的实例化时自动调用,而不能手动调用,如果像C语言一样使用malloc来为class动态分配内存,那么将无法调用构造函数。
2)C++使用运算符new和delete来完成内存动态分配,使用new时自动调用构造函数,使用完毕用delete释放内存时会自动调用析构函数。
3)使用new动态创建对象时,只需指定其数据类型,不必为该对象命名,例:
a) int *pi = new int;// pi 指向一个没有初始化的int
b) int *pi=new int( ); //初始化为0
c) string *ps=new string( ); //初始化为空字符串(对于提供了默认构造函数的类类型,没有必要对其对象进行值初始化)
d) int *pi=new int(100); //指针pi所指向的对象初始化为100
e) string *ps=new string(10,'9'); //*ps 为“9999999999”
4)new返回指定类型的指针,并且可以自动计算所需大小,例如:
a) int *p; p = new int; //返回类型为int* 类型(整数型指针),分配大小为 sizeof(int);
b) int* parr; parr = new int [100]; //返回类型为 int* 类型(整数型指针),分配大小为 sizeof(int) * 100;
c) int* p; p = (int *) malloc (sizeof(int)*128); //分配128个(可根据实际需要替换该数值)整型存储单元,并将这128个连续的整型存储单元的首地址存储到指针变量p中。
d) double *pd=(double *) malloc (sizeof(double)*12); //分配12个double型存储单元,并将首地址存储到指针变量pd中。
5)使用delete释放动态创建的对象,例:
a) delete pi ; // 释放单个对象,此时pi指针变成了悬垂指针(悬垂指针指向曾经存放对象的内存,但该对象已经不存在了)
b) delete [ ]pi; //释放数组
#include
using namespace std;
void main(){
int *arr;
int len;//数组大小
cin >> len;
//step1:分配内存
arr = (int*)malloc(len*sizeof(int));
//step2: 输入数据
for (int i = 0; i < len; i++){
cin >> arr[i]; //注意不是cin >> *arr[i];
}
//step3:使用数组
for (int i = 0; i < len; i++){
cout << "Your array is: "<< arr[i] << " ";
}
//step4: 释放内存
free(arr);
}
2) new-delete
#include
using namespace std;
void main(){
int len;//数组大小
cin >> len;
//step1:分配内存
int *arr = new int[len];
//step2: 输入数据
for (int i = 0; i < len; i++){
cin >> arr[i]; //注意不是cin >> *arr[i];
}
//step3:使用数组
cout << "Your array is: " << endl;
for (int i = 0; i < len; i++){
cout << arr[i] << " ";
}
//step4: 释放内存
delete []arr;
}
#include
using namespace std;
void main(){
int **arr;//指针的指针
int row, col;//数组大小
cin >> row >> col;
//step1-1:分配内存(行空间)
arr = (int**)malloc(row * sizeof(int*));
//step1-2:分配内存(列空间)
for (int i = 0; i < row; i++){
*(arr + i) = (int*)malloc(col * sizeof(int));
}
//step2: 输入数据
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++)
cin >> arr[i][j]; //注意不是cin >> *arr[i][j];
}
//step3:使用数组
cout << "Your array is: " << endl;
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
cout << arr[i][j] << " ";
}
cout << endl;
}
//step4: 释放内存
for (int i = 0; i < row; i++){
free(*(arr + i));
}
}
2)new-delete
#include
using namespace std;
void main(){
int row, col;//数组大小
cin >> row >> col;
//step1-1:分配内存(行空间)
int **arr = new int*[row];//指向指针的指针
//step1-2:分配内存(列空间)
for (int i = 0; i < row; i++){
arr[i] = new int[col];
}
//step2: 输入数据
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++)
cin >> arr[i][j]; //注意不是cin >> *arr[i][j];
}
//step3:使用数组
cout << "Your array is: " << endl;
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
cout << arr[i][j] << " ";
}
cout << endl;
}
//step4: 释放内存
delete []arr;
}
3)vector
#include
#include
using namespace std;
void main(){
int row, col;//数组大小
cin >> row >> col;
//step1:分配内存
vector > arr(row, vector(col));
//step2: 输入数据
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++)
cin >> arr[i][j]; //注意不是cin >> *arr[i][j];
}
//step3:使用数组
cout << "Your array is: " << endl;
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
cout << arr[i][j] << " ";
}
cout << endl;
}
//step4: 无需释放
}
1)内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
2)内存泄漏具有隐蔽性和累积性,不易被发现。
3)在C或C++程序运行时的变量主要有三种分配方式:堆分配、栈分配、全局和静态分配,内存泄漏主要发生在堆分配中,即“配置了内存后,所有指向该内存的指针都遗失了”。
4)当开发程序中使用动态存储变量较多和频繁使用函数调用时,容易发生内存管理错误,常见的有:
a) 分配一个内存块并使用其中未经初始化的内容;
b) 释放一个内存块,但继续引用其中的内容;
c) 子函数中分配的内存空间在主函数出现异常中断时、或主函数对子函数返回的信息使用结束时,没有对分配的内存进行释放;
d) 程序实现过程中分配的临时内存在程序结束时,没有释放临时内存。
5)在内存中供用户使用的内存空间分为三部分:
a) 程序存储区:
b) 静态存储区:该区数据在程序的开始就分配好内存区,在整个程序执行过程中它们所占的存储单元是固定的,在程序结束时就释放,因此静态存储区数据一般为全局变量。
c) 动态存储区:该区数据在程序执行过程中根据需要动态分配和动态释放的存储单元,动态存储区数据有三类函数形参变量、局部变量和函数调用时的现场保护与返回地址。