C++移动-only类能否在自身析构函数中将自身移动回所属管理器
结论
这种操作是未定义行为,不符合C++标准要求,完全不合法,不可在生产代码中使用。
核心原因
- 进入析构函数意味着对象的生命周期已经正式结束,C++标准不允许对已进入销毁流程的对象执行移动构造、移动赋值这类将其视为有效活跃对象的操作。哪怕你设置了
_isValid标记做有效性判断,也不能改变生命周期已经终止的事实,后续所有操作的行为都是未定义的。 - 你给出的
release方法采用值传参,调用_manager.release(std::move(*this))时会触发A的移动构造函数生成参数对象。此时移动构造的源是正在销毁的对象,即便你的移动构造函数逻辑里会把源对象的_isValid置为false,也无法规避析构函数后续继续执行带来的风险;同时如果A存在虚函数、虚继承等结构,此时对象的动态类型已经退化,移动操作的行为也会不符合预期。 - 即便移动操作碰巧执行成功,原A对象的析构逻辑还会继续执行,如果你的A类持有其他资源(比如堆内存、文件句柄等),析构函数的释放逻辑会直接导致移动到管理器里的新A对象持有悬空资源,直接触发崩溃或者数据错误。
- 该类的引用成员
AManager& _manager虽然在本场景下指向的管理器本身是存活的,但移动操作本身的合法性不会因为单个成员有效而成立。
正确实现方案
你可以额外封装一个所有权RAII包装类,把自动归还的逻辑放到包装类的析构函数中,规避操作正在销毁的A对象的问题,示例逻辑如下:
class AHolder { public: explicit AHolder(A&& a): _a(std::move(a)) {} ~AHolder() { if (_a.isValid()) { // 给A新增一个公有的isValid判断方法 globalAManager.release(std::move(_a)); } } // 同样设为移动-only类型 AHolder(const AHolder&) = delete; AHolder& operator=(const AHolder&) = delete; AHolder(AHolder&&) = default; AHolder& operator=(AHolder&&) = default; private: A _a; };
上述实现中AHolder析构时,内部持有的A对象仍处于活跃状态,移动操作完全合法。
内容的提问来源于stack exchange,提问作者Patrick Wright
相关产品推荐
相关产品推荐

