std::move 和 std::forward 之间的混淆

Confusion between std::move and std::forward

所以我只是为了我的理解写了一个 std::forward 的样本和人为的例子,但它没有按我预期的方式工作。在下面的程序中

#include <string>
#include <iostream>

struct A
{
    A(const std::string& m) : m_(m) {};
    std::string m_;
};

template<typename T>
void funcB(T&& obj)  // universal reference
{
    std::string local = std::move(obj.m_);   // using std::move on universal reference. Bad.
    std::cout << "funcB : " << local << '\n';
}

template<typename T>
void funcC(T&& obj)  // universal reference
{
    std::string local = std::forward<std::string>(obj.m_);   // using std::move on universal reference
    std::cout << "funcC : " << local << '\n';
}

template<typename T>
void funcD(T&& obj)  // universal reference
{
    T local = std::forward<T>(obj);   // using std::move on universal reference
    std::cout << "funcD : " << local.m_ << '\n';
}

int main()
{
    A obj("firstString");

   //funcA(obj);  // We get compiler error. Rvalue reference cannot be bound to Lvalue
    funcB(obj);  
    std::cout << "Main : " <<  obj.m_ << '\n';

    A obj2("secondString");
    funcC(obj2);
    std::cout << "Main : " << obj2.m_ << '\n';

    A obj3("thirdString");
    funcD(obj3);
    std::cout << "Main : " << obj3.m_ << '\n';
}

在输出中

funcB : firstString
Main : 
funcC : secondString
Main : 
funcD : thirdString
Main : thirdString

funcC中,即使我使用了通用引用并且这里它绑定到左值,但当我std::forward<std::string>时字符串被移动了。因此在最后一行,"Main:" 之后没有输出。有人可以请如何移动字符串,即使 obj 绑定到左值。

看了一本书才知道这个问题的答案。

在funcC中,std::forward<std::string>(obj.m_)相当于移动字符串。 但是在 funcD 中,std::forward 被实例化为 std::forward<struct A&>(obj),它被复制了。

在这两种情况下,您都在构造一个字符串 std::string local,并将右值引用作为参数。因此,local 是 move-constructed 来自该引用的原始对象 referred-to。

这与std::forwardstd::move没有太大关系;此外,您没有初始化一个引用("binding a reference to an lvalue" 来自 Meyers 的文本;引用将在 LHS 上)——您只是从另一个对象构造一个对象。

然而,如果不写 std::forwardstd::move 你最终会 复制 那些函数参数,因为右值引用是放在 local 声明的初始化端。

因此,在这种情况下,std::forwardstd::move 具有相同的效果。但是,它们不是一回事,通常不应视为可互换。阅读以下内容了解更多信息:

  • What's the difference between std::move and std::forward