You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

继承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部分,先后尝试两种写法均编译失败:

  1. std::enable_shared_from_this<X>::swap(first, second);,报错:No member named 'swap' in 'std::enable_shared_from_this'
  2. 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,引发逻辑异常。

针对你的代码,正确的处理方案是:

  1. 保留现有swap实现:只交换X自身的成员变量,无需处理enable_shared_from_this部分。
  2. 修正拷贝赋值运算符:
    你采用的拷贝交换(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 19:15:35