在通用参考上前进与前进

move vs forward on universal references

我正在通过对通用引用应用 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 的工作方式不一样吗?它们的工作方式有何不同(在上述代码的上下文中)?

当然,它们是不同的。如果它们相同,则您只需要一个。

move 从提供的右值或左值构造右值。 forward 破译所提供参数的实际类型。

T && 已重命名为转发引用。

在您的第一个示例中,您显式调用了 std::move,因此 str 成为一个 r 值引用,并且它的内容从 main 移动到 X 中的成员。

在第二个例子中你使用 std::forward。当 T 是右值引用时在 T 上调用 std::forward 会将右值引用转发给 operator= 并且 operator=(std::String&&) 将被调用。如果 T 是左值,则传递左值引用。因为我们有一个左值,所以 operator=(const std::string&) 将被调用,我们复制 str 而不是从它移动。

了解两件事:

1)'move'不保证能动

2) 'forward' 不转发代码。

move 是无条件运算符

forward 是一个条件运算符。

困惑??

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

通用引用意味着它们可以绑定任何东西,包括右值和左值。 move & forward 不要字面上移动任何东西而是执行转换,即它们将参数转换为 rvalue。不同之处在于 move 无条件地转换而 forward 将有条件地转换:只有当它的参数用右值初始化时它才会转换为右值。所以 move 总是投射而 forward 有时投射。 因此,上述情况下的 forward 不会清空字符串,因为 lvalue (ie str) 已传递,因此它转发 str 作为左值。