c++ - 在向量上调用 clear() 实际上不会删除 data() 中的数据?
问题描述
摘要:
似乎仅调用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.
解决方案
向量的data()
方法返回一个原始指针,指向该向量在内存中分配的数组。 clear()
如果需要,销毁该数组的内容并将向量设置size()
为 0,但不会重新分配数组本身,因此不会更改向量的capacity()
. 调用向量的shrink_to_fit()
方法会重新分配数组,以便它capacity()
匹配它size()
,如果可能的话(shrink_to_fit()
仅供参考,不保证实际做任何事情)。
std::string
此外,当自己从指针构造 a 时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
向量的情况下实现函数,例如:
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);
}
}
}
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));
}
但是,即使您想手动缓冲单词, astd::string
也会比 a 更有意义std::vector<char>
,特别是因为您正在输出std::string
值:
void splitString(const string &str, char delimiter, vector<string> * out) {
string word_buffer;
for (string::size_type i = 0; i < str.length(); ++i) {
if (str[i] == delimiter) {
out->push_back(std::move(word_buffer));
word_buffer.clear();
} else {
word_buffer.push_back(str[i]);
}
}
if (!word_buffer.empty()) {
out->push_back(std::move(word_buffer));
}
}
推荐阅读
- wordpress - 无法为我的 AWS Bitnami wordpress 网站创建证书
- javascript - Bootstrap 4:如何在第一次触发后删除 modal 的 show.bs.modal 事件
- mysql - 如何使用 IF 语句进行 JOINS - mysql
- php - 将多个值推送到数组
- postgresql - PostgreSQL:使用 LIKE 过滤掉以“K”开头的姓氏
- python - 如何从 Python 中的字符串中删除自定义空格
- r - 将许多列的内容放在一个新的单列中
- ruby - 创建了一个动态类和函数生成器,但 method_body 部分不起作用
- numpy - numpy.randomState 中使用了哪种 Mersenne Twister?
- javascript - 一次打印递归所有节点获取操作信息