seh*_*ehe 64 c++ view stdstring c++17
使用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"
Run Code Online (Sandbox Code Playgroud)
更糟糕的是,天真的方法是一个陷阱,并留下v暂时的悬挂参考:
std::string s = "hello world!";
std::string_view v(s.substr(6, 5)); // OOPS!
Run Code Online (Sandbox Code Playgroud)
我似乎记得有些东西可能会添加到标准库中以返回子字符串作为视图:
auto v(s.substr_view(6, 5));
Run Code Online (Sandbox Code Playgroud)
我可以想到以下解决方法:
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);
Run Code Online (Sandbox Code Playgroud)
坦率地说,我认为这些都不是很好.现在我能想到的最好的事情是使用别名来简化事情.
using sv = std::string_view;
sv(s).substr(6, 5);
Run Code Online (Sandbox Code Playgroud)
Ric*_*ges 39
有自由功能的路线,但除非你也提供过载,因为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);
}
Run Code Online (Sandbox Code Playgroud)
恕我直言,string_view的整个设计是一个恐怖表演,它将带我们回到一个段落错误和愤怒的客户的世界.
即使添加重载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);
}
Run Code Online (Sandbox Code Playgroud)
编译器在这里没有发现任何警告.我确信代码审查也不会.
我以前说过,我再说一遍,在对C++委员会万一有人在看,允许隐式转换从std::string到std::string_view是一个可怕的错误,只会把C++蒙羞.
在cpporg留言板上提出了这个(对我而言)相当惊人的string_view属性,我的担忧已经得到了冷漠.
这个小组的建议的共识是std::string_view绝不能从函数返回,这意味着我上面的第一个提供是不好的形式.
当然,当事故发生时(例如通过模板扩展),没有编译器帮助来捕获时间.
因此,std::string_view应该非常谨慎地使用,因为从内存管理的角度来看,它相当于指向另一个对象状态的可复制指针,这可能不再存在.但是,它在所有其他方面看起来和行为都像值类型.
因此代码如下:
auto s = get_something().get_suffix();
Run Code Online (Sandbox Code Playgroud)
get_suffix()返回时是安全的std::string(通过值或引用)
但如果get_suffix()被重构为返回a,则为UB std::string_view.
在我的简洁视图中,这意味着任何存储返回字符串的用户代码auto都会破坏,如果他们调用的库被重构而std::string_view不是代替std::string const&.
因此,从现在开始,至少对我而言,"几乎总是自动"必须变成"几乎总是自动的,除非是它的字符串".
您可以使用从std :: string到std :: string_view的转换运算符:
std::string s = "hello world!";
std::string_view v = std::string_view(s).substr(6, 5);
Run Code Online (Sandbox Code Playgroud)
这就是如何有效地创建子字符串 string_view。
#include <string>
inline std::string_view substr_view(const std::string& source, size_t offset = 0,
std::string_view::size_type count =
std::numeric_limits<std::string_view::size_type>::max()) {
if (offset < source.size())
return std::string_view(source.data() + offset,
std::min(source.size() - offset, count));
return {};
}
#include <iostream>
int main(void) {
std::cout << substr_view("abcd",3,11) << "\n";
std::string s {"0123456789"};
std::cout << substr_view(s,3,2) << "\n";
// be cautious about lifetime, as illustrated at https://en.cppreference.com/w/cpp/string/basic_string_view
std::string_view bad = substr_view("0123456789"s, 3, 2); // "bad" holds a dangling pointer
std::cout << bad << "\n"; // possible access violation
return 0;
}
Run Code Online (Sandbox Code Playgroud)