这里需要`std :: move`吗?

时间:2016-01-04 14:58:02

标签: c++ c++11

以下代码段中是否需要std::move

std::function<void(int)> my_std_function;

void call(std::function<void(int)>&& other_function)
{
  my_std_function.swap(std::move(other_function));
}

据我所知call()接受右值引用..但由于右值引用本身就是左值,为了调用swap(std::function<void(int)>&&),我必须将其重新转换为右值引用std::move

我的推理是正确的还是std::move在这种情况下可以省略(如果可以,为什么?)

4 个答案:

答案 0 :(得分:18)

std::function::swap不会通过右值参考获取其参数。它只是一个regular non-const lvalue reference。所以std::move没有用(并且可能不应该编译,因为右边引用不允许绑定到非const左值引用)。

other_function也不需要成为左值参考。

答案 1 :(得分:11)

签名是

void std::function<Sig>::swap( function& other )

因此代码不应该使用std::move进行编译(msvc具有允许此绑定的扩展名:/)

当你采用r值引用时,我认为在你的情况下你想要一个简单的赋值:

std::function<void(int)> my_std_function;

void call(std::function<void(int)>&& other_function)
{
  my_std_function = std::move(other_function); // Move here to avoid copy
}

答案 2 :(得分:3)

在这种情况下,它没有区别,因为std::function::swap采用非常量左值引用。它甚至不应该使用std::move进行编译。

如果你使用做了允许rvalues的函数,那么你 需要调用std::move,因为other_function是左值,即使它的类型是右值引用。例如:

struct Foo {
    Foo()=default;
    Foo(const Foo&) { std::cout << "copy" << std::endl; }
    Foo(Foo&&) { std::cout << "move" << std::endl; }
};

void bar (Foo&& a) {
    Foo b {a};            //copy
    Foo c {std::move(a)}; //move
}

答案 3 :(得分:1)

从某种意义上说,你是正确的 - 再次获得一个右值,你需要std::move

但是,swap调用并不需要rvalue或rvalue引用 - 只需要一个简单的&#39;左值参考。

所以,如果没有std::move演员,你就会好起来。

就移动语义而言,交换操作非常低级。您会发现最有用的动作最终都是通过一系列交换来实现的,因此交换本身不会使用移动语义。真的,他们会怎么样?