std::move 在函数上调用时做什么?

What does std::move do when called on a function?

我正在努力对一段代码进行一些更改,并且对以下情况下 std::move 的行为有疑问:

struct Timer {
   Timer (boost::asio::io_service& ios) : timer_{ios} {}
   boost::asio::steady_timer timer_;
};

struct TimerContext {
   void *ctxt_;
};

class A {
   std::function<void(Timer *, const TimerContext&)>    callback_;
   boost::asio::io_service                              ios_;
};

A的构造函数:

A::A (std::function<void(Timer *, const TimerContext&)> cb) : callback_{std::move(cb)}
{
}

回调函数定义:

void
customCallback (Timer *timer, const TimerContext& ctxt) {
...
}

main(),

for (int i = 0; i < 5; ++i) {

    A *a = new A{customCallback};

}

我对这一行有疑问: A::A (std::function<void(Timer *, const TimerContext&)> cb) : callback_{std::move(cb)}

Class A 在循环中被实例化,same customCallback 函数被移动到每个新对象的自定义构造函数。

第一个std::move不会让回调函数无法用于下一次调用吗?据我了解,如果您使用 std::move(t),则无法在该范围内再次使用 t

我对 new A 中同一函数对 std::move(cb) 的所有 5 次调用内部发生的情况感到困惑。这是实现它的正确方法吗?

仔细看A的构造函数:

A::A (std::function<void(Timer *, const TimerContext&)> cb)

函数 cb 正在按值 传递 。这意味着从通过 new:

调用函数时已经发生了该函数的副本
A *a = new A{customCallback};

构造函数初始化列表中的std::move是为了避免冗余复制到成员变量中而存在的。调用 new A 的调用者定义的原始函数保持不变。这是首选,因为复制 std::function 变量可能很昂贵。 (sizeof(cb) - 可能比您预期的要大得多)。

另一种实现方式:该函数可以作为 const 引用传递,并允许在构造函数本身中进行复制:

A::A (const std::function<void(Timer *, const TimerContext&)>& cb) : callback_{cb}

您的构造函数 A::A (std::function<void(Timer *, const TimerContext&)> cb) 通过值 获取其参数 ,即 customCallback 首先 复制 cb,然后从该副本移至 callback_

因此每次调用构造函数时,都会移动副本,而不是原始 customCallback 对象。

此外,您应该避免使用对 new 的原始调用,而更喜欢使用智能指针来避免内存泄漏,但这不是这里的问题:-)