谈谈 C++ 内存管理
有多少个new就有多少个delete
二维动态数组的写法
- 首先开辟第一维的空间,第一维是char型的指针
char **s = new char*[182];
- 在第一维的基础上,开辟第二维的空间,第二维是不定长度的char型
s[nCounts] = new char[str.length()];
- 释放二维动态数组时,规则是由内到外的,先释放第二维的空间,最后再释放第一维的空间
for (int i = 0; i < nCounts; ++i) { delete[] s[i]; // delete[col] s[i]; s[i] = NULL; } delete[] s; // delete[row] s; s = NULL;
s是二维指针,(声明)定义在main函数内,既然定义时在函数内,那么s指针就存放在内存中的栈区域中,使用new动态开辟的空间是在堆区域,堆区域用于存放数据,当然,每个数据都有它的内存地址,因此数据的地址是堆中的某一块地址,而栈中的s只是一个指针,这个指针指向堆区域的指定一块地址,当使用delete释放第二维的空间时,实质是回收堆上的虚拟地址块,而栈内的指针s并无发生变化
实现代码:
1 ///: handleString 2 #include <cstdlib> 3 #include <string> 4 #include <vector> 5 #include <fstream> 6 #include <iostream> 7 #include <algorithm> 8 9 using namespace std; 10 11 int 12 main(void) { 13 ifstream fin("E:\\totaldata.txt"); 14 ofstream fout("E:\\result.txt"); 15 16 char **s = new char*[182]; 17 18 int nCounts = 0; 19 string str; 20 vector<string> vect; 21 vector<string>::const_iterator iter; 22 23 while (getline(fin, str, '\n')) { 24 remove(str.begin(), str.end(), ' '); 25 int pos = str.find('>'); 26 str.erase(str.begin(), str.begin() + pos + 1); 27 28 vect.push_back(str); 29 30 s[nCounts] = new char[str.length()]; 31 strncpy(s[nCounts], str.c_str(), str.length()); 32 fout << nCounts + 1 << " " << s[nCounts++] << endl << endl; 33 // char* s = new char[str.length()]; 34 // strcpy(s, str.c_str()); 35 // fout << nCounts++ << " " << s << endl << endl; 36 37 // delete [] s; 38 }// End of While 39 for (int i = 0; i < nCounts; ++i) { 40 // // int col = strlen(s[i]); 41 // // delete[] s; 42 delete[] s[i]; 43 } 44 delete[] s; 45 46 fin.close(); 47 fout.close(); 48 return 0; 49 }
一开始使用strcpy,但是出错了,原因是没有在s[nCounts]末尾加上’\0’!
如果已经知道第一维的长度,假设是182,那么可以参考这种写法
- 定义
char *s[182] = {NULL};
- 动态开辟第二维数组空间
s[nCounts] = new char[str.length()];
- 释放动态数组时,因为第一维已经是事先设定好的,实质上使用new申请的堆空间只有第二维,因此只需要释放第二维的堆空间
for (int i = 0; i < nCounts; ++i) { delete[] s[i]; }
S是在main函数中定义的,因此指针数组s存放在栈空间中,栈空间存放的是182个char类型的指针,使用new为第二维开辟的空间是在堆区域,栈空间是不能回收的,因为栈是后进先出的,而且栈内保存的不只是变量,还有调用函数的地址(EIP)等等,而堆是需要回收的,如果使用new开辟一块空间,除非是使用delete回收或直到程序运行结束,否则是永远不会自动回收的,因此只能对第二维使用delete来回收堆空间
实现的代码如下:
1 ///: handleString 2 #include <cstdlib> 3 #include <string> 4 #include <vector> 5 #include <fstream> 6 #include <iostream> 7 #include <algorithm> 8 9 using namespace std; 10 11 int 12 main(void) { 13 ifstream fin("E:\\totaldata.txt"); 14 ofstream fout("E:\\result.txt"); 15 16 char *s[182] = {NULL}; 17 18 int nCounts = 0; 19 string str; 20 vector<string> vect; 21 vector<string>::const_iterator iter; 22 23 while (getline(fin, str, '\n')) { 24 remove(str.begin(), str.end(), ' '); 25 int pos = str.find('>'); 26 str.erase(str.begin(), str.begin() + pos + 1); 27 28 vect.push_back(str); 29 str += '\0'; 30 31 s[nCounts] = new char[str.length()]; 32 strcpy(s[nCounts], str.c_str()); 33 fout << nCounts + 1 << " " << s[nCounts++] << endl << endl; 34 // char* s = new char[str.length()]; 35 // strcpy(s, str.c_str()); 36 // fout << nCounts++ << " " << s << endl << endl; 37 38 // delete [] s; 39 }// End of While 40 for (int i = 0; i < nCounts; ++i) { 41 // // // int col = strlen(s[i]); 42 // // // delete[] s; 43 // int slen = strlen(s[i]); 44 // cout << &s[i] << " " << (s + i) << endl; 45 // delete[] s[i]; 46 char** ptr = (s + i); 47 cout << &s[i] << " " << ptr << endl; 48 delete[] ptr; 49 // delete[] (s + i * (strlen(s[i]) + 1)); 50 } 51 // delete[] s; 52 53 fin.close(); 54 fout.close(); 55 return 0; 56 }