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

C++单例模式进阶:如何禁止复制指向单例对象的指针?

关于单例模式的两个问题解答

一、能否阻止创建指向单例实例的多个指针副本?

首先明确:无法直接阻止裸指针的拷贝,因为指针是C++的内置类型,语言层面没有提供禁用指针赋值/拷贝的机制。你示例中的Singleton *q = Singleton::Instance();和auto A = p;这类操作,本质是拷贝内存地址值,属于语言原生支持的行为,没法从语法上直接禁止。

但可以通过设计接口来避免用户拿到裸指针,从根源上减少这种情况:

  1. 返回引用而非指针
    经典单例实现通常返回实例的引用,而非裸指针,这样用户无法轻易获取指针进行拷贝:

    class Singleton {
    private:
        Singleton() = default;
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
    public:
        static Singleton& Instance() {
            static Singleton instance; // 局部静态变量保证唯一实例
            return instance;
        }
    };
    

    此时用户只能通过Singleton::Instance()访问实例,无法直接拿到指针(除非主动用&取地址,但这属于用户刻意操作,无法完全避免)。

  2. 自定义不可拷贝的访问器类
    如果要彻底阻止用户拷贝实例的访问权,可以封装一个不可拷贝的访问器,仅允许单次获取实例的操作权限:

    class Singleton {
    private:
        Singleton() = default;
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
        ~Singleton() = default;
    
        // 自定义访问器,禁止拷贝
        class Accessor {
        private:
            Singleton* ptr;
            Accessor(Singleton* p) : ptr(p) {}
            Accessor(const Accessor&) = delete;
            Accessor& operator=(const Accessor&) = delete;
            friend class Singleton;
        public:
            // 重载运算符,让访问器能像指针/引用一样使用
            Singleton& operator*() const { return *ptr; }
            Singleton* operator->() const { return ptr; }
        };
    
    public:
        static Accessor Instance() {
            static Singleton instance;
            return Accessor(&instance);
        }
    };
    

    此时auto q = Singleton::Instance();会直接编译失败,因为Accessor的拷贝构造已被删除;用户也无法通过Accessor拷贝出额外的指针访问权。

二、能否在创建第一个对象后删除默认构造函数?

不行,因为构造函数的delete是编译期属性,无法在运行时动态修改。你示例中在构造函数内执行Singleton() = delete;完全无效——这行代码是运行时执行的,而构造函数的可用性在编译阶段就已经确定了。

如果要实现“仅允许创建一个实例”,可以通过运行时检查来阻止后续创建:

#include <stdexcept>

class Singleton {
private:
    static bool instance_created;
public:
    Singleton() {
        if (instance_created) {
            throw std::runtime_error("只能创建一个Singleton实例");
            // 也可以直接调用std::terminate()终止程序
        }
        instance_created = true;
    }
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    ~Singleton() {
        // 如果需要允许实例销毁后重新创建,可以重置标记
        instance_created = false;
    }
};

// 初始化静态标记
bool Singleton::instance_created = false;

这种方式能在运行时阻止第二个实例的创建,但无法在编译期提前报错。如果需要编译期保证唯一实例,还是得用经典单例模式——把构造函数设为私有,仅通过静态方法Instance()提供唯一实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:27:42