0

所以我只是写了一个示例和人为的例子以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中,即使我使用了通用引用并且在这里它绑定到 Lvalue,但当我这样做时,字符串也会移动std::forward<std::string>。因此在最后一行,在“Main:”之后没有输出。即使 obj 绑定到 Lvalue,有人可以请教如何移动字符串。

重读一本书后,才意识到这个问题的答案。

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

4

1 回答 1

1

std::string local在这两种情况下,您都在使用右值引用作为参数构造一个字符串。结果,local是从该引用所引用的原始对象移动构造的。

std::forward这与std::move;没有太大关系。此外,您没有初始化引用(这是 Meyers 文本中“将引用绑定到左值”的来源;引用将在 LHS 上)——您只是从另一个对象构造一个对象。

但是,确实,如果不编写,std::forward否则std::move您最终会复制local这些函数参数,因为右值引用将被丢弃在's 声明的初始化端。

所以,在这种情况下,std::forwardstd::move有同样的效果。但是,它们不是一回事,通常不应被视为可互换的。阅读以下内容以获取更多信息:

于 2018-02-19T12:05:37.353 回答