本文介绍了如何有效地获取`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);//世界"

更糟糕的是,这种幼稚的方法是一个陷阱,并且给 v 留下了一个对临时对象的悬空引用:

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

似乎记得像标准库中可能有一个附加功能可以将子字符串作为视图返回:

auto v(s.substr_view(6, 5));

我可以想到以下解决方法:

std::string_view(s).substr(6, 5);std::string_view(s.data()+6, 5);//甚至更糟":std::string_view(s).remove_prefix(6).remove_suffix(1);

坦率地说,我认为这些都不是很好.现在我能想到的最好的办法是使用别名来简化事情的冗长.

使用 sv = std::string_view;sv(s).substr(6, 5);
解决方案

有自由函数路线,但除非你也为 std::string 提供重载,否则它就是一个蛇坑.

>

#include #include std::string_view sub_string(std::string_view s,std::size_t p,std::size_t n = std::string_view::npos){返回 s.substr(p, n);}int main(){使用命名空间 std::literals;自动源 = "foobar"s;//这很好很优雅...自动栏 = sub_string(source, 3);//但是呃-哦...bar = sub_string(foobar"s, 3);}

恕我直言,string_view 的整个设计是一场恐怖秀,它将把我们带回一个充满段错误和愤怒客户的世界.

更新:

即使为 std::string 添加重载也是一场恐怖表演.看看你是否能发现微妙的段错误定时炸弹......

#include #include std::string_view sub_string(std::string_view s,std::size_t p,std::size_t n = std::string_view::npos){返回 s.substr(p, n);}std::string sub_string(std::string&&s,std::size_t p,std::size_t n = std::string::npos){返回 s.substr(p, n);}std::string sub_string(std::string const& s,std::size_t p,std::size_t n = std::string::npos){返回 s.substr(p, n);}int main(){使用命名空间 std::literals;自动源 = "foobar"s;自动栏 = sub_string(std::string_view(source), 3);//但是呃-哦...bar = sub_string(foobar"s, 3);}

编译器在这里没有发现任何需要警告的地方.我确信代码审查也不会.

我之前已经说过,我会再说一遍,以防 c++ 委员会的任何人正在观看,允许从 std::stringstd 的隐式转换::string_view 是一个可怕的错误,它只会让 C++ 声名狼藉.

更新

在 cpporg 留言板上提出这个(对我来说)string_view 相当令人震惊的属性后,我的担忧得到了冷漠.

这个小组的共识是 std::string_view 绝不能从函数返回,这意味着我上面的第一个提供是错误的形式.

当然没有编译器帮助捕捉偶然发生的时间(例如通过模板扩展).

因此,std::string_view 应该非常小心地使用,因为从内存管理的角度来看,它相当于一个指向另一个对象状态的可复制指针,它可能不再存在.但是,它在所有其他方面的外观和行为都类似于值类型.

这样的代码:

auto s = get_something().get_suffix();

get_suffix() 返回 std::string(通过值或引用)时是安全的

但是如果 get_suffix() 被重构为返回一个 std::string_view 则是 UB.

在我看来,这意味着任何使用 auto 存储返回字符串的用户代码都会中断,如果他们调用的库被重构为返回 std::string_view代替 std::string const&.

所以从现在开始,至少对我来说,几乎总是自动"将不得不变成几乎总是自动的,除非是字符串".

Using http://en.cppreference.com/w/cpp/string/basic_string_view as a reference, I see no way to do this more elegantly:

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

Worse, the naive approach is a pitfall and leaves v a dangling reference to a temporary:

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

I seem to remember something like there might be an addition to the standard library to return a substring as a view:

auto v(s.substr_view(6, 5));

I can think of the following workarounds:

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);

Frankly, I don't think any of these are very nice. Right now the best thing I can think of is using aliases to simply make things less verbose.

using sv = std::string_view;
sv(s).substr(6, 5);
解决方案

There's the free-function route, but unless you also provide overloads for std::string it's a snake-pit.

#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);
}

IMHO the whole design of string_view is a horror show which will take us back to a world of segfaults and angry customers.

update:

Even adding overloads for std::string is a horror show. See if you can spot the subtle segfault timebomb...

#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);
}

The compiler found nothing to warn about here. I am certain that a code review would not either.

I've said it before and I'll say it again, in case anyone on the c++ committee is watching, allowing implicit conversions from std::string to std::string_view is a terrible error which will only serve to bring c++ into disrepute.

Update

Having raised this (to me) rather alarming property of string_view on the cpporg message board, my concerns have been met with indifference.

The consensus of advice from this group is that std::string_view must never be returned from a function, which means that my first offering above is bad form.

There is of course no compiler help to catch times when this happens by accident (for example through template expansion).

As a result, std::string_view should be used with the utmost care, because from a memory management point of view it is equivalent to a copyable pointer pointing into the state of another object, which may no longer exist. However, it looks and behaves in all other respects like a value type.

Thus code like this:

auto s = get_something().get_suffix();

Is safe when get_suffix() returns a std::string (either by value or reference)

but is UB if get_suffix() is ever refactored to return a std::string_view.

Which in my humble view means that any user code that stores returned strings using auto will break if the libraries they are calling are ever refactored to return std::string_view in place of std::string const&.

So from now on, at least for me, "almost always auto" will have to become, "almost always auto, except when it's strings".

这篇关于如何有效地获取`std::string`的子字符串的`string_view`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 19:47