首页 > 解决方案 > 函数执行完成后,如何使函数内部分配的内存保持分配状态?

问题描述

我用 C++ 编写了一个函数,它接受一个字符串和一个字符作为参数,并返回一个字符串数组,其中每个数组元素都是字符串中的一个单词。

string* breakS(string s, const char* c){
    string::iterator it;
    int j=0, i = 1;
    for(it = s.begin();it!=s.end();it++){
        if(*it == *c){
            i++;
        }
    }
    string* R = new string[i];
    for(it = s.begin();it!=s.end();it++){
        if(*it != *c){
            R[j].push_back(*it);
        } else {
            j++;
        }
    }
    return R;
}

因为我永远不知道输入字符串会有多少个单词,所以我不得不动态分配字符串数组。

该程序运行良好,但是当函数完成执行时,由 string* R = new string[i]分配的内存将被释放,因此我相信如果字符串输入足够大,则该程序重新调整的字符串数组可能是覆盖。

函数执行完成后,如何使函数内部分配的内存保持分配状态?

标签: c++memory-management

解决方案


你的理解有点不对劲。

R当函数退出时,变量本身的内存确实被释放,R局部变量也是如此breakS()。ButR是一个指针,当函数退出时,R所指向的内存,被分配的内存,new[]不会被自动释放。delete[]完成使用后,它成为调用者对该内存的责任,例如:

string* breakS(string s, char c, int &numWords){
    numWords = 0;
    string::iterator it;
    int i = 1;
    for(it = s.begin(); it != s.end(); ++it){
        if (*it == c){
            ++i;
        }
    }
    string* R = new string[i];
    i = 0;
    for(it = s.begin(); it != s.end(); ++it){
        if (*it != c){
            R[i].push_back(*it);
        } else {
            ++i;
        }
    }
    numWords = i;
    return R;
}
int numWords;
string *words = breakS("some,string,of,words", ',', numWords);
for (int i = 0; i < numWords; ++i) {
    // use words[i] as needed...
}
delete[] words;

处理这种内存管理的更好方法是使用std::vector

#include <vector>

std::vector<string> breakS(string s, char c){
    string::iterator it;
    int i = 1;
    for(it = s.begin(); it != s.end(); ++it){
        if (*it == c){
            ++i;
        }
    }
    std::vector<string> R(i);
    i = 0;
    for(it = s.begin(); it != s.end(); ++it){
        if (*it != c){
            R[i].push_back(*it);
        } else {
            ++i;
        }
    }
    return R;
}
std::vector<string> words = breakS("some,string,of,words", ',');
for(size_t i = 0; i < words.size(); ++i){
    // use words[i] as needed...
}

然后可以进一步简化,因为您不需要预先调整 a 的大小std::vector来添加新元素,它会根据需要动态增长,例如:

std::vector<string> breakS(string s, char c){
    std::vector<string> R;
    string::size_type start = 0, idx = s.find(c);
    while (idx != string::npos){
        R.push_back(s.substr(start, idx-start));
        start = idx + 1;
        idx = s.find(c, start);
    }
    if (start < s.size()){
        R.push_back(s.substr(start));
    }
    return R;
}

推荐阅读