【问题标题】:move vs forward on universal references在通用参考上前进与前进
【发布时间】:2016-01-02 08:44:24
【问题描述】:

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

【问题讨论】:

标签: c++ move forward


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      了解两件事:

      1) 'move' 不保证会移动

      2) 'forward' 不转发代码。

      move 是一个无条件运算符

      forward 是一个条件运算符。

      困惑??

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

      【讨论】:

        【解决方案4】:

        通用引用意味着它们显然可以绑定任何东西,包括右值和左值。 move & forward 不移动任何文字,而是执行强制转换,即他们将参数强制转换为rvalue。区别在于move 无条件强制转换,而forward 将有条件强制转换:仅当其参数使用右值初始化时,它才会强制转换为右值。所以move 总是强制转换,而forward 有时会强制转换。 因此,上述情况下的forward 不会清空字符串,因为传递了lvalue (ie str),因此它会将str 作为左值转发。

        【讨论】:

        • 感谢您提供更简单的答案!
        • 查看 Scott Meyer 的“有效的现代 C++:改进 C++11 和 C++14 使用的 42 种特定方法”以获得更好的解释。祝你好运!
        猜你喜欢
        • 2012-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多