c++ - std::move 和 std::forward 之间的混淆

标签 c++ c++11 stdmove

<分区>

所以我只是在编写 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 ,即使我使用了通用引用并且这里它绑定(bind)到左值,当我执行 std::forward<std::string> 时字符串也会被移动.因此在最后一行,“Main:”之后没有输出。即使 obj 绑定(bind)到左值,有人可以请教如何移动字符串吗?

在重读一本书后,才知道这个问题的答案。

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

最佳答案

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

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

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

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

关于c++ - std::move 和 std::forward 之间的混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48865711/

相关文章:

C++ linux 套接字在单个调用中将字符串数组(char **)作为连接字符串发送

.net - 什么是 .NET,我如何知道我的项目是否使用它?

c++ - GCC 导致 lambda 捕获的参数包的段错误

c++ - C++ 中的 std::move() 和 xvalue

c++ - 为什么我的代码打印 r 值 2 次而不是 rvalue 和 lvalue?

c++ - std::move 可以移动内置类型或 c 指针或数组吗

c++ - Qt 多页 TIFF

c++ - "Move or throw"使用三元运算符

c++ - 包含在 std::regex 搜索中,使用 std::regex_token_iterator 从 std::sub_match 中排除

c++ - 如何获取当前线程的std::thread?