我正在试用一个关于通用引用的程序,方法是对它们应用std::move
和std::forward
。直到今天,我认为两者都是相同的,但在这个程序中(如下所示),输出让我感到惊讶。
#include <iostream>
#include <string>
#include <utility>
using namespace std;
class X
{
string take="";
public:
template<class T>
void pass1 (T &&str) // str is a universal reference as it can bind to anything, both rvalue and lvalue references
{
take=move(str);
}
template<class T>
void pass2 (T &&str)
{
take=forward<T>(str);
}
void show()
{
cout<<"take = "<<take<<"\n";
}
}obj;
int main()
{
cout<<"using move on universal reference:-\n";
string str="he is there";
cout<<"str = "<<str<<'\n';
obj.pass1(str);
obj.show();
if (str.empty())
cout<<"str is empty\n\n";
else
cout<<"str isnt empty\n\n";
cout<<"using forward on universal reference:-\n";
str="he was there";
cout<<"str = "<<str<<'\n';
obj.pass2(str);
obj.show();
if (str.empty())
cout<<"str is empty\n\n";
else
cout<<"str isnt empty\n\n";
return 0;
}
输出:
using move on universal reference:-
str = he is there
take = he is there
str is empty
using forward on universal reference:-
str = he was there
take = he was there
str isnt empty
*/
我的问题是:
move
和forward
的工作方式相似吗?它们如何以不同的方式工作(与上述代码相关)?答案 0 :(得分:2)
当然,它们是不同的。如果它们是相同的,你只需要一个。
move
从提供的右值或左值构造rvalue。 forward
解密所提供参数的实际类型。
答案 1 :(得分:2)
T &&
已重命名为转发引用。
在您的第一个示例中,您明确调用std::move
,以便str
成为r值引用,并将其内容从main移动到X
中的成员。
在第二个示例中,您使用std::forward
。当std::forward
是r值引用时,在T
上调用T
会将r值引用转发给operator=
并调用operator=(std::String&&)
。如果T
是l值,则传递l值引用。由于我们有一个l值,operator=(const std::string&)
将被调用,我们会复制str
而不是从中移动。
答案 2 :(得分:1)
理解两件事:
1)&#39;移动&#39;不保证移动
2)&#39;前进&#39;不转发代码。
move是一个无条件的运算符
forward是一个条件运算符。
困惑??
答案 3 :(得分:0)
通用引用意味着它们可以与任何东西绑定,包括rvalues和lvalues。 move
&amp; forward
不要在任何情况下移动,而是执行演员表,即他们将参数投射到rvalue
。区别在于move
无条件投射,而forward
将有条件地投射:只有当其参数用rvalue初始化时,它才会转换为右值。所以move
总是会施放,而forward
有时会施放。
因此,上述案例中的forward
在传递lvalue (ie str)
时不会清空字符串,因此它将str
作为左值转发。