C++ 如何在函数返回期间使用带有 std::string 的移动语义?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12011426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use move semantics with std::string during function return?
提问by EddieV223
Possible Duplicate:
C++11 rvalues and move semantics confusion
可能的重复:
C++11 右值和移动语义混淆
What I think is correct is
我认为正确的是
std::string GetLine()
{
std::string str;
std::getline(std::cin, str);
return std::move(str);
}
But at this link http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html( check the header part Returning an explicit rvalue-reference from a function)
但是在这个链接http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html(检查标题部分 Returning an explicit rvalue-reference from a功能)
which is #1 google search hit for move semantics shows a similar function signature as
这是 #1 google search hit for move semantics 显示了类似的函数签名
int&& GetInt()
{
int x = 0;
// code here
return std::move(x);
}
From what I read at other places && means rvalue referenceso in this case its returning a reference to an object that doesn't exist.
从我在其他地方读到的内容 && 表示右值引用,因此在这种情况下,它返回对不存在对象的引用。
So which is it?
那么它是哪个?
(Yes I know moving an int has no real benifit but the question is whether to use the return type of std::string or std::string&& in the first function. And if that is how it should be done for all types.)
(是的,我知道移动 int 没有真正的好处,但问题是在第一个函数中是否使用 std::string 或 std::string&& 的返回类型。如果这是对所有类型都应该这样做的方式。)
回答by bames53
You are absolutely correct that the int&& GetInt()
example is wrong, and is returning a reference to an object that is destroyed. However, unless I missed it, the link you posted does not actually show any code returning a reference to a localvariable. Instead I see a reference to a globalvariable being returned, which is okay.
您完全正确,该int&& GetInt()
示例是错误的,并且正在返回对已销毁对象的引用。但是,除非我错过了,否则您发布的链接实际上并未显示任何返回对局部变量的引用的代码。相反,我看到一个对全局变量的引用被返回,这没关系。
Here is how you use move semantics when returning:
以下是返回时如何使用移动语义:
std::string func()
{
std::string rv;
/* ... */
return rv;
}
You generally should not use std::move()
when returning an object. The reason for this is that moving is already implicitly allowed anytime RVO could occur, and using std::move()
will suppress RVO. So using std::move()
will never be better and will often be worse than just returning normally.
您通常不应该std::move()
在返回对象时使用。这样做的原因是在 RVO 可能发生的任何时候都隐式允许移动,并且使用std::move()
将抑制 RVO。因此,使用std::move()
永远不会更好,而且通常比正常返回更糟糕。
Again, using std::move()
can be worse than simply naming the variable to be returned because it suppresses the return value optimization. The return value optimization allows for an object to be returned to the caller without needing to copy that object
同样,使用std::move()
可能比简单地命名要返回的变量更糟糕,因为它抑制了返回值优化。返回值优化允许将对象返回给调用者,而无需复制该对象
in a
return
statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function's return value— [class.copy] 12.8/31
在
return
具有类返回类型的函数中的语句中,当表达式是与函数返回类型具有相同 cv-unqualified 类型的非易失性自动对象(函数或 catch-clause 参数除外)的名称时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作— [class.copy] 12.8/31
But using std::move()
prevents the return expression from being the nameof the object you're returning. Instead the expression is more complicated and the language is no longer allowed to give it special handling.
但是 usingstd::move()
可以防止返回表达式成为您要返回的对象的名称。相反,表达式更加复杂,并且不再允许语言对其进行特殊处理。
The reason just naming the object is not worse than using std::move()
is because there's another rule that says an expression can already be treated as an rvalue without needing std::move()
.
仅仅命名对象并不比使用更糟糕的原因std::move()
是因为还有另一条规则表明表达式已经可以被视为右值而无需std::move()
.
When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.
当满足或将满足复制操作的省略条件时,除了源对象是函数参数,并且要复制的对象由左值指定时,选择复制构造函数的重载决议是首先执行,就好像对象是由右值指定的一样。
回答by eq-
Answering the question, sort of: return a string
. Don't move
anything, but rather use (rely on) RVO:
回答这个问题,有点:返回 a string
。什么都不做move
,而是使用(依赖)RVO:
std::string func()
{
std::string rv;
/* ... */
return rv;
}
This is how it generally should be done. You can't return an (r-value or not) reference to a temporary.
这就是通常应该这样做的方式。您不能返回对临时值的(r 值与否)引用。
回答by Kerrek SB
No need to say return std::move(str);
if str
is a local variable: If the variable satisfies the criteria for return-value optimisation, then in a return
statement the variable will bind to an rvalue reference.
无需说明return std::move(str);
ifstr
是否为局部变量:如果变量满足返回值优化的标准,则在return
语句中该变量将绑定到右值引用。
Also, beware that you should probably not return a reference to a local variable, neither lvalue nor rvalue reference.
另外,请注意,您可能不应该返回对局部变量的引用,无论是左值还是右值引用。
All told, you should have:
总而言之,你应该有:
int foo() { int x; /*...*/ return x; }
std::string bar() { std::string str; /*...*/ return str; }