如何有效地得到`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::stringstd::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 :: stringstd :: string_view的转换运算符:

 std::string s = "hello world!"; std::string_view v = std::string_view(s).substr(6, 5);