c – std :: move(T \u0026\u0026)和临时对象.临时从哪里来?

我很好奇为什么我无法编译下面的代码.

这是无意义的代码(我知道),但是我最初在一些其他代码中遇到了使用完美转发等模板的问题.

我设法将问题缩小到std :: move / std :: forward / std :: remove_reference,我很好奇为什么它需要一个临时的首先…

#include <utility>
#include <stdio.h>

struct Foo {
    Foo(Foo&& other) {
        printf("Foo::(Foo&&) %p\n",this);
    }
    Foo() {
        printf("Foo::() %p\n",this);
    }
    ~ Foo() {
        printf("Foo::~Foo() %p\n",this);
    }
};

void test(Foo&& t)
{
    // OK: Works fine and "f1" is is constructed with Foo::Foo(Foo&& other)
    // Foo f1 = std::move(t);

    // ERROR: Here it is trying to  bind a temporary Foo to a non-const lvalue
    // I can't figure out why it needs to create a temporary.
    Foo& f2 = std::move(t);
}

int main()
{
    Foo foo;
    test(std::move(foo));
}

编译与Clang(3.7),它给我以下错误

23 : error: non-const lvalue reference to type 'Foo' cannot bind to a temporary of type 'typename std::remove_reference<Foo &>::type' (aka 'Foo')
Foo& f2 = std::move(t);
^ ~~~~~~~~~~~~
1 error generated.
Compilation Failed

我明白我不能将一个临时的绑定到一个非const引用,并且有很多问题回答为什么不允许.

我希望代码只是提到foo,主要是Foo& f2,因此不需要临时.

Visual Studio接受代码,但GCC和Clang无法编译;虽然Visual Studio当然不是那么严格.

解决方法

好:
Foo& f2 = std::move(t);

f2是一个参考,所以你在哪里移动?你根本没有移动.

std :: move返回一个rvalue引用;您不能将其分配给一个左值引用变量(考虑到一个rvalue引用可以是临时引用).因此,编译器会抱怨您为临时引用引用(因为std :: move会创建编译器认为是临时引用,即rvalue引用).

没有实际创造一个临时的;这只是std :: move返回一个rvalue引用,你不能被赋值给一个左值引用. (唯一可能的“临时”是由t参数引用的一个,它被声明为一个右值引用;它发生的是你的例子传递的东西不是一个临时的,通过移动,但它可以很容易地通过一个实际的临时参考).

简而言之,问题不在于它需要一个临时的,而是将一个rvalue引用(可能是临时的)引用到一个lvalue引用变量. Clang错误消息有点误导,因为它意味着存在一个临时的,而rvalue引用可能不会实际上是指临时的. GCC产生:

test2.cc: In function 'void test(Foo&&)': test2.cc:23:24: error:
invalid initialization of non-const reference of type 'Foo&' from an
rvalue of type 'std::remove_reference<Foo&>::type {aka Foo}'
     Foo& f2 = std::move(t);

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...