如何有效地得到`std :: string`的子串的`string_view`
使用http://en.cppreference.com/w/cpp/string/basic_string_view作为参考,我看不出更优雅的做法:
std::string s = "hello world!"; std::string_view v = s; v = v.substr(6, 5); // "world"
更糟糕的是,这种天真的做法是一个陷阱,并且暂时引用一个暂时的:
std::string s = "hello world!"; std::string_view v(s.substr(6, 5)); // OOPS!
我似乎记得像标准库可能会添加一个子string作为视图:
auto v(s.substr_view(6, 5));
我可以想到以下解决方法:
std::string_view(s).substr(6, 5); std::string_view(s.data()+6, 5); // or even "worse": std::string_view(s).remove_prefix(6).remove_suffix(1);
坦率地说,我认为这些都不是很好。 现在我能想到的最好的方法就是使用别名来简化事情。
using sv = std::string_view; sv(s).substr(6, 5);
有自由function的路线,但除非你也提供了重载的std::string
这是一个蛇坑。
#include <string> #include <string_view> std::string_view sub_string( std::string_view s, std::size_t p, std::size_t n = std::string_view::npos) { return s.substr(p, n); } int main() { using namespace std::literals; auto source = "foobar"s; // this is fine and elegant... auto bar = sub_string(source, 3); // but uh-oh... bar = sub_string("foobar"s, 3); }
恕我直言,string_view的整个devise是一个恐怖节目,将带我们回到segfaults和愤怒的客户的世界。
更新:
即使增加std::string
重载是一个恐怖的表演。 看看你能否发现微妙的段落时间炸弹…
#include <string> #include <string_view> std::string_view sub_string(std::string_view s, std::size_t p, std::size_t n = std::string_view::npos) { return s.substr(p, n); } std::string sub_string(std::string&& s, std::size_t p, std::size_t n = std::string::npos) { return s.substr(p, n); } std::string sub_string(std::string const& s, std::size_t p, std::size_t n = std::string::npos) { return s.substr(p, n); } int main() { using namespace std::literals; auto source = "foobar"s; auto bar = sub_string(std::string_view(source), 3); // but uh-oh... bar = sub_string("foobar"s, 3); }
编译器在这里没有发现任何警告。 我确信代码审查也不会。
我已经说过了,我会再说一遍,以防c ++委员会的任何人都在观察, 允许从std::string
到std::string_view
隐式转换是一个可怕的错误,这只会使c ++陷入不幸 。
更新
在cpporg留言板上提出了这个对我来说相当令人担忧的string_view属性,我的担心已经被冷淡所左右了。
从这个小组的build议的共识是std::string_view
绝不能从一个函数返回,这意味着我的第一个产品是不好的forms。
当发生这种情况时(例如通过模板扩展),当然没有编译器可以帮助捕捉时间。
因此,应该尽量使用std::string_view
,因为从内存pipe理的angular度来看,它相当于一个可复制的指针,指向另一个对象的状态,这个对象可能不再存在。 然而,它看起来和行为在所有其他方面像一个值types。
像这样的代码:
auto s = get_something().get_suffix();
当get_suffix()
返回一个std::string
(通过值或引用)
但是如果get_suffix()被重构为返回一个std::string_view
则是UB。
在我的卑微观点意味着任何用户代码存储返回的string使用auto
将打破,如果他们正在调用的库重构,以返回std::string_view
代替std::string const&
。
所以从现在开始,至less对于我来说,“几乎总是汽车”将不得不成为“几乎总是自动的,除非是弦乐”。
你可以使用从std :: string到std :: string_view的转换运算符:
std::string s = "hello world!"; std::string_view v = std::string_view(s).substr(6, 5);