继承enable_shared_from_this的类的swap方法实现问题(C++20)
问题描述
我为继承自enable_shared_from_this<X>的类X实现了swap方法及拷贝赋值运算符,代码如下:
class X : public enable_shared_from_this<X> { int x; friend void swap(X& x1, X& x2) { using std::swap; swap(x1.x, x2.x); } X& operator=(X other) { swap(*this, other); } // ... 其他成员 };
我尝试在swap方法中交换enable_shared_from_this部分,先后尝试两种写法均编译失败:
std::enable_shared_from_this<X>::swap(first, second);,报错:No member named 'swap' in 'std::enable_shared_from_this'swap(static_cast<std::enable_shared_from_this<X>>(first), static_cast<std::enable_shared_from_this<X>>(second));,报错:Calling a protected constructor of class 'std::enable_shared_from_this' protected constructor can only be used to construct a base class subobject
最终我在赋值运算符中添加了std::enable_shared_from_this<X>::operator=(other);,但感觉swap方法不完整且混合了编程风格。请问在C++20中正确的处理方式是什么?
正确处理方式
在C++20中,std::enable_shared_from_this不需要手动交换其内部状态,核心原因如下:
enable_shared_from_this的本质是持有一个与自身对象绑定的弱引用(weak_ptr),作用是让对象能安全生成指向自己的shared_ptr。- 交换两个
X对象时,各自的enable_shared_from_this子对象的弱引用必须保持与自身对象的绑定关系,强行交换会导致后续shared_from_this()返回错误的shared_ptr,引发逻辑异常。
针对你的代码,正确的处理方案是:
- 保留现有swap实现:只交换
X自身的成员变量,无需处理enable_shared_from_this部分。 - 修正拷贝赋值运算符:
你采用的拷贝交换(copy-swap)手法本身不需要调用enable_shared_from_this::operator=——临时对象的enable_shared_from_this子对象本来就和临时对象绑定,临时对象销毁后不会影响当前对象的绑定关系。同时,编译器自动生成的拷贝构造函数会正确初始化新对象的enable_shared_from_this子对象,使其指向新对象自身。
修正后的代码示例:
#include <memory> #include <utility> class X : public std::enable_shared_from_this<X> { public: X(int val) : x(val) {} // 编译器生成的拷贝构造函数即可满足需求 X(const X&) = default; friend void swap(X& x1, X& x2) noexcept { using std::swap; swap(x1.x, x2.x); // 无需处理enable_shared_from_this部分 } X& operator=(X other) noexcept { swap(*this, other); return *this; } private: int x; };
额外说明:
- 如果类是仅可移动的,同样不需要手动处理
enable_shared_from_this的移动/交换,基类的移动构造函数会自动将源对象的弱引用转移到新对象,同时清空源对象的弱引用,符合预期行为。 - 永远不要手动修改或交换
enable_shared_from_this的内部状态,它的设计目标是自动管理与自身对象的绑定关系,手动干预会彻底破坏这种绑定逻辑。
内容的提问来源于stack exchange,提问作者traveh
相关产品推荐
相关产品推荐

