我最近听到赫伯·萨特 (Herb Sutter) 的一次演讲,他提出通过的理由std::vector
and std::string
by const &
大部分已经消失了。他建议现在最好编写如下所示的函数:
std::string do_something ( std::string inval )
{
std::string return_val;
// ... do stuff ...
return return_val;
}
据我了解,return_val
在函数返回时将是一个右值,因此可以使用移动语义返回,这是非常便宜的。然而,inval
仍然比引用的大小(通常作为指针实现)大得多。这是因为一个std::string
有各种组件,包括指向堆的指针和成员char[]
用于短字符串优化。所以在我看来,通过引用传递仍然是一个好主意。
谁能解释一下为什么赫伯会这么说?
赫伯之所以说出这样的话,就是因为这样的案例。
假设我有功能A
它调用函数B
,它调用函数C
. And A
传递一个字符串B
并进入C
. A
不知道或不关心C
; all A
知道的是B
。那是,C
是一个实现细节B
.
假设 A 定义如下:
void A()
{
B("value");
}
如果 B 和 C 将字符串取为const&
,那么它看起来像这样:
void B(const std::string &str)
{
C(str);
}
void C(const std::string &str)
{
//Do something with `str`. Does not store it.
}
一切都很好。你只是传递指针,没有复制,没有移动,每个人都很高兴。C
需要一个const&
因为它不存储字符串。它只是使用它。
现在,我想做一个简单的改变:C
需要将字符串存储在某处。
void C(const std::string &str)
{
//Do something with `str`.
m_str = str;
}
你好,复制构造函数和潜在的内存分配(忽略短字符串优化 (SSO) https://stackoverflow.com/questions/10315041/meaning-of-acronym-sso-in-the-context-of-stdstring)。 C++11 的移动语义应该能够删除不必要的复制构造,对吧?和A
通过临时;没有理由C
应该必须copy数据。它应该带着给予它的东西潜逃。
除非它不能。因为它需要一个const&
.
如果我改变C
按值获取其参数,这只会导致B
复制到该参数中;我一无所获。
所以如果我刚刚过去str
通过所有函数的值,依赖于std::move
打乱数据,我们就不会有这个问题。如果有人想坚持下去,他们就可以。如果他们不这样做,哦,好吧。
是不是比较贵?是的;转移到一个值比使用引用更昂贵。是不是比正版便宜?不适用于具有 SSO 的小字符串。值得做吗?
这取决于您的用例。您有多讨厌内存分配?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)