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
的原始调用,而更喜欢使用智能指针来避免内存泄漏,但这不是这里的问题:-)
我正在努力对一段代码进行一些更改,并且对以下情况下 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
的原始调用,而更喜欢使用智能指针来避免内存泄漏,但这不是这里的问题:-)