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

C++禁止直接实例化的类是否应删除移动构造与移动赋值运算符

场景需求
  • 禁止用户直接调用构造函数创建Foo类实例,因此将构造函数设为私有
  • 所有实例生命周期自动管理,不允许用户直接操作Foo类裸实例,要求统一通过std::shared_ptr<Foo>访问实例
现有实现代码
#include <iostream>
#include <memory>
 
class Foo : public std::enable_shared_from_this<Foo> {
private:     // 禁止用户直接调用该构造函数创建实例                    
    Foo(int num):num_(num) { std::cout << "Foo::Foo\n"; }
public:
    Foo(const Foo&) = delete;
    Foo(Foo&&) = default;
    Foo& operator=(const Foo&) = delete;
    Foo& operator=(Foo&&) = default;

public:
    ~Foo() { std::cout << "Foo::~Foo\n"; } 

    int DoSth(){std::cout << "hello world" << std::endl; return 0;}

    std::shared_ptr<Foo> getPtr() { return shared_from_this();}

    static std::shared_ptr<Foo> Create() {
        Foo* foo = new Foo(5);
        return std::shared_ptr<Foo>(foo);
    }

private:
    int num_;

};

int main()
{
    auto sp = Foo::Create();
    sp->DoSth();

    Foo& foo = *sp.get();
    auto sp1 = foo.getPtr();

    Foo foo1(std::move(foo));

    std::cout << sp.use_count() << std::endl;
}
核心疑问
  • 是否应当将移动构造函数、移动赋值运算符标记为deleted?
  • 顾虑场景:若一个线程正在调用移动构造函数,同时另一个线程调用类的成员函数,是否会引发线程安全问题?需要该场景下的合理设计建议。
设计建议

必须删除移动构造与移动赋值运算符

保留默认移动构造/赋值直接违背你最初的设计目标:

  • 现有测试代码里已经可以写出Foo foo1(std::move(foo));这种逻辑,直接在栈上构造出了脱离shared_ptr管控的独立Foo实例,这个实例的生命周期完全不受智能指针管理,出作用域会自动析构,完全绕过了你设计的生命周期管理规则。
  • 一旦用户在这种非shared_ptr托管的栈实例上调用getPtr(),会直接触发未定义行为:enable_shared_from_this内部的弱引用指针只有在对象被shared_ptr持有时才会被正确初始化,在栈对象上调用shared_from_this()要么直接抛出异常,要么出现野指针崩溃。

关于线程安全顾虑的说明

你担心的「移动构造和成员函数并发调用」的问题,本质不是移动构造本身的问题,核心逻辑如下:

  • C++标准明确规定,多个线程在无外部同步的前提下,对同一个对象同时执行写操作(移动构造会修改源对象的内容,属于写操作)和读写访问(调用成员函数如果涉及成员读写)本身就是数据竞争,属于未定义行为,这是通用的并发规则,和你是否保留移动构造无关。
  • 删除移动构造之后,用户根本无法写出从托管实例移动构造新独立对象的代码,从根源上杜绝了这种错误使用场景的出现。所有对Foo实例的访问都必须通过shared_ptr完成,shared_ptr的引用计数操作本身是线程安全的,你只需要按照普通类的并发规则,在Foo的成员函数里对内部共享成员的访问做好线程同步即可,不会额外引入风险。

额外优化提示

你现在Create里先new再构造shared_ptr的写法能跑通,因为构造函数是私有的没法直接用std::make_shared,如果想省一次内存分配,可以加个私有的空标签结构体做跳板,用std::make_shared构造,不做这个优化也完全不影响功能。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 16:03:34