在向量上调用clear()实际上不会删除data()中的数据吗?

时间:2019-06-08 00:07:11

标签: c++ vector stl erase shrink

摘要

在向量上调用clear()似乎不足以清除它。

vector_full_of_stuff.clear();

我必须先叫clear(),然后叫shrink_to_fit()才能完全删除其中的所有数据。

vector_full_of_stuff.clear();
// AND THEN  
vector_full_of_stuff.shrink_to_fit();

有什么作用?之所以成为问题,是因为当我在向量上调用data()时,会包含我认为在代码前面调用clear()时应该清除的内容。

其他详细信息

我正在进行计算机网络分配,其中必须将PASV命令结果解析为IP和端口号。在解析以逗号分隔的虚拟PASV命令结果时,我注意到,如果我解析三位数后跟两位数字,那么我在调用data()时就可以从上一次解析中获得第三位数,即使我不应该(?)因为我之前叫过clear()

  

例如。
  PASV命令结果= 209,202,252,54,19,15
  解析时,“ 252”中的“ 2”会延续到“ 19”中。

代码

// this one actually deletes data
void splitString(string str, char delimiter, vector<string> * out) {
    vector<char> word_buffer;
    for (int i = 0; i < str.length(); ++i) {
        if (str[i] == delimiter) {
            out->push_back(word_buffer.data());
            word_buffer.clear();
            word_buffer.shrink_to_fit();
        } else {
            word_buffer.push_back(str[i]);
        }
    }
    out->push_back(word_buffer.data());
    word_buffer.clear();
}
// 

// this one doesn't
// the only thing that's different about this one 
// is that its missing shrink_to_fit()
void splitString(string str, char delimiter, vector<string> * out) {
    vector<char> word_buffer;
    for (int i = 0; i < str.length(); ++i) {
        if (str[i] == delimiter) {
            out->push_back(word_buffer.data());
            word_buffer.clear();
            // word_buffer.shrink_to_fit(); // need this to delete data
        } else {
            word_buffer.push_back(str[i]);
        }
    }
    out->push_back(word_buffer.data());
    word_buffer.clear();
}
//

// main driver code
int main() {
    vector<string> user_input_tokens;
    string port = "209,202,252,54,19,15";
    splitString(port, ',', &user_input_tokens);
    for (string str : user_input_tokens) {
        cout << str << ".";
    }
}
//

预期输出:

209.202.252.54.19.15.

实际输出:

209.202.252.542.192.152.

1 个答案:

答案 0 :(得分:3)

向量的data()方法返回指向向量在内存中分配的数组的原始指针。 clear()会在需要时破坏该数组的 contents 并将向量的size()设置为0,但不会重新分配数组本身,因此不会更改向量的{{1 }}。调用向量的capacity()方法会重新分配数组,以便其shrink_to_fit()与其数组capacity()匹配(如果可能的话(size()仅是建议性的,不能保证 做任何事情)。

此外,当单独从shrink_to_fit()指针构造std::string时,char数据需要以空值结尾,而您的数据不是。您需要在使用char*之前将空终止符插入向量:

data()

否则,在构造字符串时,只需考虑向量的void splitString(const string &str, char delimiter, vector<string> * out) { vector<char> word_buffer; for (int i = 0; i < str.length(); ++i) { if (str[i] == delimiter) { word_buffer.push_back('\0'); out->push_back(word_buffer.data()); word_buffer.clear(); } else { word_buffer.push_back(str[i]); } } if (!word_buffer.empty()) { word_buffer.push_back('\0') out->push_back(word_buffer.data()); } } ,就不需要空终止符:

size()

话虽这么说,还有其他方法可以完全不需要void splitString(const string &str, char delimiter, vector<string> * out) { vector<char> word_buffer; for (int i = 0; i < str.length(); ++i) { if (str[i] == delimiter) { out->push_back(string(word_buffer.data(), word_buffer.size())); // alternatively: // out->emplace_back(word_buffer.data(), word_buffer.size()); word_buffer.clear(); } else { word_buffer.push_back(str[i]); } } if (!word_buffer.empty()) { out->push_back(string(word_buffer.data(), word_buffer.size())); // alternatively: // out->emplace_back(word_buffer.data(), word_buffer.size()); } } 向量来实现splitString()函数,例如:

word_buffer

Live Demo

void splitString(const string &str, char delimiter, vector<string> * out) {
    string::size_type start = 0, pos = str.find(delimiter);
    while (pos != string::npos) {
        out->push_back(str.substr(start, pos-start));
        start = pos + 1;
        pos = str.find(delimiter, start);
    }
    if (start < str.size()) {
        if (start > 0) {
            out->push_back(str.substr(start));
        } else {
            out->push_back(str);
        }
    }
}

Live Demo

但是,即使您想手动缓冲单词,void splitString(const string &str, char delimiter, vector<string> * out) { istringstream iss(str); string word; while (getline(iss, word, delimiter)) out->push_back(std::move(word)); } std::string更有意义,尤其是因为您正在输出std::vector<char>值:

std::string

Live Demo