小编典典

将 const std::string & 作为参数传递的日子结束了吗?

all

我听过 Herb Sutter 最近的一次演讲,他认为过去std::vector和过去std::string的理由const &基本上已经不复存在了。他建议现在最好编写如下函数:

std::string do_something ( std::string inval )
{
   std::string return_val;
   // ... do stuff ...
   return return_val;
}

我知道return_val在函数返回时这将是一个右值,因此可以使用非常便宜的移动语义返回。但是,inval仍然比引用的大小(通常实现为指针)大得多。这是因为
astd::string具有各种组件,包括指向堆的指针和char[]用于短字符串优化的成员。所以在我看来,通过引用传递仍然是一个好主意。

谁能解释为什么 Herb 会这么说?


阅读 307

收藏
2022-03-04

共1个答案

小编典典

赫布之所以这么说,就是因为这样的案例。

假设我有调用函数的A函数B,它调用函数C。并将A一个字符串传递BC.
A不知道也不关心C;众所周知A的是B。也就是说,C是 的实现细节B

假设 A 定义如下:

void A()
{
  B("value");
}

如果 B 和 C 取字符串 by const&,那么它看起来像这样:

void B(const std::string &str)
{
  C(str);
}

void C(const std::string &str)
{
  //Do something with `str`. Does not store it.
}

一切都很好。你只是在传递指针,没有复制,没有移动,每个人都很开心。C需要 aconst&因为它不存储字符串。它只是使用它。

现在,我想做一个简单的改变:C需要将字符串存储在某个地方。

void C(const std::string &str)
{
  //Do something with `str`.
  m_str = str;
}

你好,复制构造函数和潜在的内存分配。C++11
的移动语义应该可以消除不必要的复制构造,对吧?并A通过一个临时的;没有理由C必须 复制 数据。它应该带着给它的东西潜逃。

除非它不能。因为它需要一个const&.

如果我更改C为按值获取其参数,那只会导致B复制到该参数中;我一无所获。

因此,如果我只是str通过所有函数按值传递,依靠std::moveshuffle
数据,我们就不会有这个问题。如果有人想坚持下去,他们可以。如果他们不这样做,哦,好吧。

它更贵吗?是的; 移动到一个值比使用引用更昂贵。它比副本便宜吗?不适用于带有 SSO 的小字符串。值得做吗?

这取决于您的用例。你有多讨厌内存分配?

2022-03-04