我很好奇为什么我无法编译下面的代码.
这是无意义的代码(我知道),但是我最初在一些其他代码中遇到了使用完美转发等模板的问题.
我设法将问题缩小到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,因此不需要临时.
解决方法
好:
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);