返回字符串时传递string_view

Passing string_view when returning string

提问人:dpardo 提问时间:11/8/2023 最后编辑:TylerHdpardo 更新时间:11/8/2023 访问量:92

问:

我一直在阅读使用 的好处,以及为什么应该在参数列表中使用它。而且我知道通常不建议返回 a。std::string_viewstring_view

但是,假设我有一个简单的函数,它接受添加后缀。我能想到两种方法:string

std::string AddSuffix(std::string_view inputString)
{
    return std::string(inputString) + "!";
}

std::string AddSuffix(std::string inputString)
{
    return inputString + "!";
}

如果我必须复制任何一种方式,是否有任何理由使用一种而不是另一种?inputString

C++ 字符串 字符串视图

评论

0赞 273K 11/8/2023
第二种选择更具可读性,更可取,但它过于简单化。通常,函数具有更多独立于参数值的返回点,例如第一个选项更可取。投票结束为“基于意见”的问题。return {};
2赞 wohlstad 11/8/2023
第一种方法的一个优点是:它不需要构造一个 for .A 可以在没有副本的情况下构造,例如从以零结尾的字符串文字。std::stringinputStringstring_view
1赞 HolyBlackCat 11/8/2023
如果我们计算复制/移动,按值传递可能会更好,特别是如果您这样做。但实际上我不会打扰,并且会使用一个参数来与其他所有内容保持一致,然后(或等效的)添加 .std::stringstd::move(inputString) + "!"std::string_viewstd::format"!"
0赞 HolyBlackCat 11/8/2023
@wohlstad......除了函数体无论如何都要从它构造。:(std::string
0赞 wohlstad 11/8/2023
@HolyBlackCat你当然是对的。我只是参考界面设计。

答:

0赞 Daniel Langr 11/8/2023 #1

这两个变体的问题在于它们创建了 2 个对象,这两个对象都需要分配内存(如果这些字符串足够长而无法放入 SSO 缓冲区)。这里的原因是(按值)返回一个新对象。std::stringoperator+string

如果要保存一个分配,可以按如下方式修改大小写:std::string_view

std::string AddSuffix(std::string_view inputString)
{
  std::string temp;
  temp.reserve(inputString.size() + 1);
  temp = inputString;
  temp += "!";
  return temp;
}

在这种情况下,应用 RVO 时只需要一个分配(所有主要实现都将应用它)。

现场演示显示分配:https://godbolt.org/z/44P37qhP3

评论

1赞 phuclv 11/8/2023
temp += "!";temp.push_back('!');
0赞 Daniel Langr 11/8/2023
@phuclv 你能解释一下为什么吗?
0赞 phuclv 11/8/2023
因为它需要 Or 扫描字符串中的 null 终止符以追加,所以复制所有字符直到该点,一些错误的实现甚至可能从中创建新的 std::string 并追加。OTOH ,或者如果需要,只需增加大小,然后在末尾写一个字符std::string::operator+=(char*)std::string::append(char*)std::string::push_back(char)operator+=(char)std::string::append(char)