如何移动含std::bind绑定this成员函数的C++对象?
问题描述
我在类中通过std::bind将成员函数绑定到当前对象的this指针,代码如下:
class SubObject { public: SubObject(std::function<void()> handler) : _handler(handler) { } private: std::function<void()> _handler; }; class A { public: A(): _sub_object(std::bind(&A::wrapper, this)) { } private: SubObject _sub_object; void wrapper() { /* ... */ } };
当我给类A添加移动构造函数时,发现传入SubObject的绑定函数无法正常工作——因为它绑定的是原对象的this指针,移动后原对象的this已经失效:
A(A&& other) { std::swap(other._sub_object, _sub_object); }
请问能否移动通过std::bind绑定this生成的函数?
解决方案
直接移动这种绑定了原对象this的std::function行不通,因为std::bind会把this指针固定绑定到原对象的地址,移动操作不会自动更新这个指针。要解决这个问题,有几种实用思路:
1. 改用智能指针动态获取当前对象
让A继承std::enable_shared_from_this,用lambda捕获shared_from_this()来替代std::bind,这样调用时会自动获取当前对象的有效指针:
#include <memory> class A : public std::enable_shared_from_this<A> { public: A(): _sub_object([this]() { if (auto self = shared_from_this()) { self->wrapper(); } }) { } A(A&& other) noexcept { std::swap(other._sub_object, _sub_object); } private: SubObject _sub_object; void wrapper() { /* ... */ } };
这种方式下,即使对象被移动,lambda调用时拿到的self始终是当前有效对象的指针,不会指向已失效的原对象。
2. 移动时重新绑定当前this
如果一定要用std::bind,不要直接交换_sub_object,而是在移动构造时为新对象重新创建绑定自身this的函数:
A(A&& other) noexcept : _sub_object(std::bind(&A::wrapper, this)) { // 可选:将原对象的handler置空,避免无效调用 other._sub_object = SubObject(nullptr); }
相当于抛弃原对象的旧绑定,给新对象生成一个全新的、指向自身的绑定函数,确保调用时指向正确实例。
3. 给SubObject加更新handler的接口
给SubObject添加成员函数来更新内部存储的std::function,移动时先交换对象,再手动更新handler为绑定当前this的版本:
class SubObject { public: SubObject(std::function<void()> handler) : _handler(std::move(handler)) { } void updateHandler(std::function<void()> new_handler) { _handler = std::move(new_handler); } private: std::function<void()> _handler; }; class A { public: A(): _sub_object(std::bind(&A::wrapper, this)) { } A(A&& other) noexcept { std::swap(other._sub_object, _sub_object); // 更新handler为绑定当前this的版本 _sub_object.updateHandler(std::bind(&A::wrapper, this)); } private: SubObject _sub_object; void wrapper() { /* ... */ } };
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

