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

如何阻止通过默认初始化或new关键字创建FibonacciMemoization实例

解决单例模式中std::make_shared与私有构造/析构的冲突

要实现仅通过FibonacciMemoization::getInstance()创建实例的单例,必须把类的构造、析构、拷贝构造、赋值运算符设为私有或删除,阻止外部直接new或栈上创建对象。但std::make_shared需要访问这些私有成员,导致编译错误,以下是几种可行的解决方法:

方案1:声明std::make_shared和std::default_delete为友元

通过友元授权,让std::make_shared能调用私有构造函数,std::default_delete能调用私有析构函数,同时保留make_shared内存分配连续的优势。

#include <memory>

class FibonacciMemoization {
private:
    // 私有构造、析构,禁止拷贝和赋值
    FibonacciMemoization() = default;
    ~FibonacciMemoization() = default;
    FibonacciMemoization(const FibonacciMemoization&) = delete;
    FibonacciMemoization& operator=(const FibonacciMemoization&) = delete;

    // 授权std::make_shared访问私有构造
    template<typename T, typename... Args>
    friend std::shared_ptr<T> std::make_shared(Args&&... args);
    // 授权std::default_delete访问私有析构
    template<typename T>
    friend struct std::default_delete;

    static std::shared_ptr<FibonacciMemoization> instance;

public:
    static std::shared_ptr<FibonacciMemoization> getInstance() {
        if (!instance) {
            instance = std::make_shared<FibonacciMemoization>();
        }
        return instance;
    }

    // 示例记忆化斐波那契计算函数
    int calculate(int n) {
        static std::vector<int> memo;
        if (n < memo.size()) return memo[n];
        if (n <= 1) {
            memo.resize(n+1);
            memo[n] = n;
            return n;
        }
        int res = calculate(n-1) + calculate(n-2);
        memo.push_back(res);
        return res;
    }
};

// 初始化静态实例指针
std::shared_ptr<FibonacciMemoization> FibonacciMemoization::instance = nullptr;

方案2:直接用new构造shared_ptr

放弃make_shared的内存效率,直接在getInstance中用new创建对象,再传入shared_ptr构造函数。这种方式代码更简单,无需友元声明。

#include <memory>

class FibonacciMemoization {
private:
    FibonacciMemoization() = default;
    ~FibonacciMemoization() = default;
    FibonacciMemoization(const FibonacciMemoization&) = delete;
    FibonacciMemoization& operator=(const FibonacciMemoization&) = delete;

    static std::shared_ptr<FibonacciMemoization> instance;

public:
    static std::shared_ptr<FibonacciMemoization> getInstance() {
        if (!instance) {
            instance = std::shared_ptr<FibonacciMemoization>(new FibonacciMemoization());
        }
        return instance;
    }

    // 示例成员函数
    int calculate(int n) {
        // 斐波那契计算逻辑
        if (n <= 1) return n;
        return calculate(n-1) + calculate(n-2);
    }
};

std::shared_ptr<FibonacciMemoization> FibonacciMemoization::instance = nullptr;

方案3:用内部辅助类封装创建逻辑

通过私有内部类Helper来访问构造和析构,避免使用友元,保持类的封装性。

#include <memory>

class FibonacciMemoization {
private:
    FibonacciMemoization() = default;
    ~FibonacciMemoization() = default;
    FibonacciMemoization(const FibonacciMemoization&) = delete;
    FibonacciMemoization& operator=(const FibonacciMemoization&) = delete;

    // 内部辅助类,负责创建和销毁实例
    struct Helper {
        static FibonacciMemoization* create() {
            return new FibonacciMemoization();
        }
        static void destroy(FibonacciMemoization* ptr) {
            delete ptr;
        }
    };

    static std::shared_ptr<FibonacciMemoization> instance;

public:
    static std::shared_ptr<FibonacciMemoization> getInstance() {
        if (!instance) {
            instance = std::shared_ptr<FibonacciMemoization>(
                Helper::create(), Helper::destroy
            );
        }
        return instance;
    }

    // 示例成员函数
    int calculate(int n) {
        // 斐波那契计算逻辑
        if (n <= 1) return n;
        return calculate(n-1) + calculate(n-2);
    }
};

std::shared_ptr<FibonacciMemoization> FibonacciMemoization::instance = nullptr;

以上三种方案都能实现需求:阻止外部直接创建实例,同时让getInstance正常返回std::shared_ptr类型的单例对象,编译运行无报错。

内容的提问来源于stack exchange,提问作者Jason Rich Darmawan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:33:11