首页 > 解决方案 > 在函数上调用 std::move 时会做什么?

问题描述

我正在对一段代码进行一些更改,并且在以下情况下对理解 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)}

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

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

我很困惑std::move(cb)new A. 这是执行它的正确方法吗?

标签: c++stdmove

解决方案


仔细看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}

推荐阅读