将 "force" 的右值引用强制转换为 return 值中的移动 - 说明
Casting to rvalue reference to "force" a move in a return value - clarification
好的,我开始了解右值引用的要点(我认为)。我有我正在写的这段代码片段:
#include <iostream>
using namespace std;
std::string get_string()
{
std::string str{"here is your string\n"};
return std::move(str); // <----- cast here?
}
int main ()
{
std::string my_string = std::move(get_string()); // <----- or cast here?
std::cout << my_string;
return 0;
}
所以我有一个简单的示例,其中我有一个 returns 字符串副本的函数。我已经读到它对 return 任何对本地临时变量的引用都是不好的(并得到了核心转储来证明它!)所以我已经打折尝试了。
在 main()
的赋值中,我不想复制构造我想要 move-construct/assign 的字符串,以避免复制太多字符串。
Q1:我 return get_string()
中临时变量的 "copy" - 但我已将 return 值转换为右值红色.那是毫无意义还是做任何有用的事情?
Q2:假设Q1的答案是我不需要那样做。然后我是将临时变量的新副本移动到 my_string
,还是直接将临时变量 str
移动到 my_string
。
问题 3:为了将字符串 return 值存储到 "external" 中,您需要的最少副本数是多少(在我的例子中是在 main() ) 变量,你是怎么做到的(如果我还没有实现的话)?
I return a "copy" of the temp var in get_string() - but I have cast the return value to rvalue-red. Is that pointless or is that doing anything useful?
在那种情况下您不必使用 std::move
,因为按值返回的局部变量对您来说是 "implicitly moved"。标准中对此有特殊规定。在这种情况下,您的举动是悲观,因为它可以防止 RVO(clang 对此发出警告)。
Q2: Assuming Q1's answer is I don't need to do that. Then am I moving the fresh copy of the temp variable into my_string, or am I moving directly the temp variable str into my_string.
您不需要 std::move
调用 get_string()
的结果。 get_string()
是一个 prvalue,这意味着 my_string
的移动构造函数将被自动调用(C++17 之前)。在 C++17 及更高版本中,强制复制省略 将确保不会发生 moves/copies(使用 prvalues)。
Q3: what is the minimum number of copies that you need in order to get a string return value stored into an "external" (in my case in main()) variable, and how do you do that (if I am not already achieving it)?
取决于标准以及是否发生 RVO。如果发生 RVO,您将拥有 0 个副本和 0 个移动。如果你的目标是 C++17 并从 prvalue 初始化,你保证有 0 个副本和 0 个移动。如果两者都没有发生,您可能只有一个动作 - 我不明白为什么要在这里发生任何复制。
您不需要在作为局部变量的 return 值上使用 std::move
。 The compiler does that for you:
If expression is an lvalue expression that is the (possibly parenthesized) name of an automatic storage duration object declared in the body or as a parameter of the innermost enclosing function or lambda expression, then overload resolution to select the constructor to use for initialization of the returned value is performed twice: first as if expression were an rvalue expression (thus it may select the move constructor), and if no suitable conversion is available, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object's type (possibly cv-qualified), overload resolution is performed a second time, with expression considered as an lvalue (so it may select the copy constructor taking a reference to non-const).
好的,我开始了解右值引用的要点(我认为)。我有我正在写的这段代码片段:
#include <iostream>
using namespace std;
std::string get_string()
{
std::string str{"here is your string\n"};
return std::move(str); // <----- cast here?
}
int main ()
{
std::string my_string = std::move(get_string()); // <----- or cast here?
std::cout << my_string;
return 0;
}
所以我有一个简单的示例,其中我有一个 returns 字符串副本的函数。我已经读到它对 return 任何对本地临时变量的引用都是不好的(并得到了核心转储来证明它!)所以我已经打折尝试了。
在 main()
的赋值中,我不想复制构造我想要 move-construct/assign 的字符串,以避免复制太多字符串。
Q1:我 return
get_string()
中临时变量的 "copy" - 但我已将 return 值转换为右值红色.那是毫无意义还是做任何有用的事情?Q2:假设Q1的答案是我不需要那样做。然后我是将临时变量的新副本移动到
my_string
,还是直接将临时变量str
移动到my_string
。问题 3:为了将字符串 return 值存储到 "external" 中,您需要的最少副本数是多少(在我的例子中是在 main() ) 变量,你是怎么做到的(如果我还没有实现的话)?
I return a "copy" of the temp var in get_string() - but I have cast the return value to rvalue-red. Is that pointless or is that doing anything useful?
在那种情况下您不必使用 std::move
,因为按值返回的局部变量对您来说是 "implicitly moved"。标准中对此有特殊规定。在这种情况下,您的举动是悲观,因为它可以防止 RVO(clang 对此发出警告)。
Q2: Assuming Q1's answer is I don't need to do that. Then am I moving the fresh copy of the temp variable into my_string, or am I moving directly the temp variable str into my_string.
您不需要 std::move
调用 get_string()
的结果。 get_string()
是一个 prvalue,这意味着 my_string
的移动构造函数将被自动调用(C++17 之前)。在 C++17 及更高版本中,强制复制省略 将确保不会发生 moves/copies(使用 prvalues)。
Q3: what is the minimum number of copies that you need in order to get a string return value stored into an "external" (in my case in main()) variable, and how do you do that (if I am not already achieving it)?
取决于标准以及是否发生 RVO。如果发生 RVO,您将拥有 0 个副本和 0 个移动。如果你的目标是 C++17 并从 prvalue 初始化,你保证有 0 个副本和 0 个移动。如果两者都没有发生,您可能只有一个动作 - 我不明白为什么要在这里发生任何复制。
您不需要在作为局部变量的 return 值上使用 std::move
。 The compiler does that for you:
If expression is an lvalue expression that is the (possibly parenthesized) name of an automatic storage duration object declared in the body or as a parameter of the innermost enclosing function or lambda expression, then overload resolution to select the constructor to use for initialization of the returned value is performed twice: first as if expression were an rvalue expression (thus it may select the move constructor), and if no suitable conversion is available, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object's type (possibly cv-qualified), overload resolution is performed a second time, with expression considered as an lvalue (so it may select the copy constructor taking a reference to non-const).