在向量上调用 clear() 并不会真正删除 data() 中的数据?
Calling clear() on a vector does not actually delete data in 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()
。
ex.
PASV Command Result = 209,202,252,54,19,15
The "2" from "252" carries over into "19" when parsing.
代码:
// 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()
方法 returns 指向矢量在内存中分配的数组的原始指针。 clear()
在需要时销毁该数组的 contents 并将向量的 size()
设置为 0,但不会重新分配数组本身,因此不会更改向量的capacity()
。调用向量的 shrink_to_fit()
方法会重新分配数组,以便它的 capacity()
匹配它的 size()
,如果可能(shrink_to_fit()
仅供参考,而不是 保证 实际做任何事情)。
此外,当从 char*
指针本身构造 std::string
时,char 数据需要是 null-terminated,但您的数据不是。在使用 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('[=10=]');
out->push_back(word_buffer.data());
word_buffer.clear();
} else {
word_buffer.push_back(str[i]);
}
}
if (!word_buffer.empty()) {
word_buffer.push_back('[=10=]')
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));
}
但是,即使您想手动缓冲单词,std::string
也比 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));
}
}
总结:
似乎仅在矢量上调用 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()
。
ex.
PASV Command Result = 209,202,252,54,19,15
The "2" from "252" carries over into "19" when parsing.
代码:
// 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()
方法 returns 指向矢量在内存中分配的数组的原始指针。 clear()
在需要时销毁该数组的 contents 并将向量的 size()
设置为 0,但不会重新分配数组本身,因此不会更改向量的capacity()
。调用向量的 shrink_to_fit()
方法会重新分配数组,以便它的 capacity()
匹配它的 size()
,如果可能(shrink_to_fit()
仅供参考,而不是 保证 实际做任何事情)。
此外,当从 char*
指针本身构造 std::string
时,char 数据需要是 null-terminated,但您的数据不是。在使用 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('[=10=]');
out->push_back(word_buffer.data());
word_buffer.clear();
} else {
word_buffer.push_back(str[i]);
}
}
if (!word_buffer.empty()) {
word_buffer.push_back('[=10=]')
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));
}
但是,即使您想手动缓冲单词,std::string
也比 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));
}
}