在普遍参考上移动vs前进

时间:2015-10-05 16:02:57

标签: c++ move forward

我正在试用一个关于通用引用的程序,方法是对它们应用std::movestd::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
*/

我的问题是:

  1. 为什么输出不同?
  2. 不是moveforward的工作方式相似吗?它们如何以不同的方式工作(与上述代码相关)?

4 个答案:

答案 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是一个条件运算符。

困惑??

请观看此视频:     https://www.youtube.com/watch?v=BezbcQIuCsY

答案 3 :(得分:0)

通用引用意味着它们可以与任何东西绑定,包括rvalues和lvalues。 move&amp; forward不要在任何情况下移动,而是执行演员表,即他们将参数投射到rvalue。区别在于move无条件投射,而forward将有条件地投射:只有当其参数用rvalue初始化时,它才会转换为右值。所以move总是会施放,而forward有时会施放。 因此,上述案例中的forward在传递lvalue (ie str)时不会清空字符串,因此它将str作为左值转发。