我对内存分配和复制非常敏感,因此,如果函数需要
std::string
对象作为输入,我总是使用 const std::string &
。
最近,我发现如果我传入一个
const std::string &
,std::string
将会构造一个char[]
对象。请看这个:
#include <iostream>
#include <string>
using namespace std;
void test_string(const std::string & s) { // use std::string_view here is better
// it can avoid local variable allocation
printf("%p\n", s.data());
}
int main() {
char aa[] = "asd";
test_string(aa);
printf("%p\n", aa);
}
我用
const std::string &
更改了std::string_view
,它解决了不必要的构造或副本。所以,我认为std::string_view
值得在任何地方使用。
我把所有的
const std::string &
都换成了std::string_view
,如果有地方需要用std::string
,我就用.data()
来获取字符串。
问题发生在以下情况。
inline std::vector<std::string_view> Split(std::string_view str, std::string_view delim, const bool trim_empty = false) {
if (str.empty()) return {};
size_t pos, last_pos = 0, len;
std::vector<std::string_view> tokens;
while (true) {
pos = str.find(delim, last_pos);
if (pos == std::string::npos) pos = str.size();
len = pos - last_pos;
if (!trim_empty || len != 0) tokens.push_back(str.substr(last_pos, len));
if (pos == str.size()) break;
else last_pos = pos + delim.size();
}
return tokens;
}
我用它来将
string
拆分为vector
,如您所见,std::stringview
避免了复制和大内存分配。
但是问题发生在使用 std::stringview 时。
std::string str = "asd\nbn\ncd\n\n";
std::unordered_map<std::string, int> m;
m["asd"] = 2;
const auto & v = Split(str, "\n");
const auto & it = m.find(v.front().data());
此操作失败,因为
v.front().data()
返回整个字符串,而不是第一部分。
我知道这是由于字符串流中没有
"\0"
造成的。
除了构建一个
std::string_view
之外,似乎没有找到正确的std::string(v.front().data())
的好方法。
那么,有什么办法可以让
.data()
如期而至呢?或者用 std::stringview 替换 const std::string & 只是不是一个总是好的选择?
std::string_view::data()
返回一个不一定以 null 终止的指针。std::string::data()
返回一个always以null结尾的指针。
既然你无论如何都要构造临时
std::string
,请正确执行:std::string{v.front()}
将构造正确长度的字符串。
或者,如果这是
Split
的唯一用途,则根本不要使用 std::string_view
,如果仅使用 string_view
来构造 string
似乎不会有太多收获.