在我回答你的问题之前,你似乎弄错了一件事:在 C++11 中按值获取并不总是意味着复制。如果传递右值,则为moved(假设存在可行的移动构造函数)而不是被复制。和std::string
确实有一个移动构造函数。
与 C++03 不同,在 C++11 中,按值获取参数通常是惯用的做法,原因我将在下面解释。另请参阅StackOverflow 上的问答有关如何接受参数的更通用的指南。
为什么我们不采用右值引用str
?
因为这将导致无法传递左值,例如:
std::string s = "Hello";
S obj(s); // s is an lvalue, this won't compile!
If S
只有一个接受右值的构造函数,上面的代码无法编译。
副本不会很贵,尤其是考虑到类似的东西std::string
?
如果你传递一个右值,那就是moved into str
,最终将被移入data
。不会执行任何复制操作。另一方面,如果您传递左值,则该左值将是copied into str
,然后搬进data
.
总而言之,右值有两次移动,左值有一次复制和一次移动。
作者决定复制然后搬家的原因是什么?
首先,正如我上面提到的,第一个并不总是副本;这就是说,答案是:“因为它是有效的(移动std::string
物品便宜)且简单".
假设移动成本较低(此处忽略 SSO),则在考虑此设计的整体效率时实际上可以忽略它们。如果我们这样做,我们就会有一份左值副本(如果我们接受对左值的引用,我们就会拥有一份左值副本)const
)并且没有右值的副本(如果我们接受对左值的引用,我们仍然会有一个副本const
).
这意味着按值获取与按左值引用获取一样好const
当提供左值时,并且当提供右值时更好。
P.S.:为了提供一些背景,我相信这是问答OP指的是。