第一次在这里注册帐户,但我非常喜欢这个网站。
我正在尝试创建一个函数来接收一个 const char 数组并返回该数组的一部分。该函数与数组一起接收两个值,指示要提取的部分中第一个字符的索引和最后一个字符的索引。
关于我正在尝试的棘手部分是我正在创建一个临时数组变量来将这部分保存在一个函数中并且鉴于该部分的大小不能保证是一个常量我正在使用动态分配必要空间的内存,这就是我遇到问题的地方。
只要函数返回任何信息,函数就会结束,程序就没有机会释放备用内存。如果我删除变量,我将无法返回信息。
我尝试创建一个单独的指针变量来指向形成后的信息,但是一旦内存被释放,信息似乎就无法恢复。
有问题解除分配的程序:
char* seperateString(const char* a, int b, int c) {
// This is simply to assure that I don't allocated a negative size
if (b < c) {
cout << "***Error with \"seperateString\" function***" << endl << endl;
return '\0';
}
char* seperated = new char[c - b + 2];
int i = 0;
int j = b;
for (; i <= c - b; i++)
seperated[i] = a[j++];
seperated[i] = '\0';
char* send = seperated;
delete[] seperated;
return send;
}
int main() {
cout << "Program Iniciated." << endl << endl;
const int a = 6, b = 11;
const char* toBeSeperated = "Hello there, I have missed you.";
char *ari = seperateString(toBeSeperated, 6, 11);
cout << "Sentence is: " << toBeSeperated << endl << endl
<< "Extracted portion is: " << ari << endl << endl;
cin.get();
return 0;
}
程序在主函数中按预期工作。
int main() {
cout << "Program Iniciated." << endl << endl;
// variable a and b hold the beginning and last index values of the portion
// that is wanted to extract.
const int a = 6, b = 11;
// This is an example sentence |------| this is the portion being extracted.
const char* toBeSeperated = "Hello there, I have missed you.";
// variable holding extracted portion.
// created with the size necessary to hold the portion plus a \0.
char* seperated = new char[b -a +2];
//Given that a and b are index values 1 has to be added for size
//Additionally an extra space is require for \0
//i is held outside the for loop to allow to access it after it completes the cycle
//so it's able to assing \0 after the last character.
int i = 0;
//j holds the value of the first index
int j = a;
for (; i <= b - a; i++)
seperated[i] = toBeSeperated[j++];
seperated[i] = '\0';
cout << "Sentence is: " << toBeSeperated << endl << endl
<< "Extracted portion is: " << seperated << endl << endl;
delete[] seperated;
cin.get();
return 0;
}
最后,这是为了防止内存泄漏。
最佳答案
正如您所指出的,我们必须有实际存储函数结果的内存,因此我们不能在返回之前释放动态分配的数组。这给我们留下了两个选择:
- 在我们调用之前分配内存,并向被调用函数提供指向该内存的指针和大小(不够优雅)
- 确保我们以安全的方式传回指向已分配内存的指针
然而,在这两种情况下,我们都必须确保手动释放内存。智能指针非常适合这种用例,特别是 std::unique_ptr .
这是一个正常运行的程序:
#include <iostream>
#include <memory>
std::unique_ptr<char[]> seperateString(const char* a, int b, int c) {
using namespace std;
// This is simply to assure that I don't allocated a negative size
if (c < b) {
cout << "***Error with \"seperateString\" function***" << endl << endl;
return '\0';
}
auto seperated = std::unique_ptr<char[]>(new char[c - b + 2]);
int i = 0;
int j = b;
for (; i <= c - b; i++)
seperated[i] = a[j++];
seperated[i] = '\0';
return seperated;
}
int main() {
using namespace std;
cout << "Program Iniciated." << endl << endl;
const int a = 6, b = 11;
const char* toBeSeperated = "Hello there, I have missed you.";
auto ari = seperateString(toBeSeperated, 0, 5);
cout << "Sentence is: " << toBeSeperated << endl << endl
<< "Extracted portion is: " << ari.get() << endl << endl;
cin.get();
return 0;
}
唯一指针获取动态分配资源的所有权,并在资源本身在离开作用域时被销毁时释放(即解除分配)资源。
函数中seperateString
, 我们构建了 unique_ptr
通过运算符 new[]
指向动态分配的字符数组的指针.从这一点开始,我们不需要管理动态分配的内存,因为它绑定(bind)到智能指针的生命周期 seperated
.每当seperated
被销毁,其析构函数将调用运算符 delete[]
在构造时分配给它的数组指针上。
等等,seperated
在函数返回时被销毁,那么我们不是回到原点,因为在我们开始在调用代码中使用它之前释放了内存吗?不,因为我们要返回 unique_ptr<char[]>
按值,编译器将资源的所有权从函数本地 seperated
移出指向调用站点本地的唯一指针 ari
唯一指针,通过移动构造函数构造它。现在函数调用中分配的内存的命运与 ari
的生命周期相关。 ,当它超出范围时,内存将被释放而不会泄漏。
关于c++ - 在函数内释放动态内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57368729/