当前位置: 首页 > news >正文

More Effective C++ 条款26:限制某个类所能产生的对象数量

More Effective C++ 条款26:限制某个类所能产生的对象数量


核心思想通过控制类的实例化过程,限制程序中该类的对象数量,可以防止资源过度使用,确保系统资源合理分配,并实现单例或有限实例模式。

🚀 1. 问题本质分析

1.1 对象数量限制的需求

  • 单例模式:确保一个类只有一个实例,并提供全局访问点
  • 有限资源管理:例如数据库连接池、线程池等,需要限制实例数量以避免资源耗尽
  • 唯一性约束:某些类在逻辑上应该是唯一的,比如应用程序的配置管理器

1.2 实现限制的挑战

  • 防止直接实例化:需要拦截所有创建对象的途径(构造函数、拷贝构造、赋值操作等)
  • 继承带来的复杂性:派生类可能无意中创建多个实例
  • 线程安全:在多线程环境中,需要安全地控制实例数量
// 基础示例:单例模式
class Singleton {
public:static Singleton& getInstance() {static Singleton instance;  // 局部静态变量,C++11保证线程安全return instance;}// 删除拷贝构造函数和赋值操作符Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;private:Singleton() = default;  // 私有构造函数~Singleton() = default;
};

📦 2. 问题深度解析

2.1 对象计数技术

// 使用静态计数限制对象数量
class LimitedInstances {
public:LimitedInstances() {if (count >= maxInstances) {throw std::runtime_error("Too many instances");}++count;}~LimitedInstances() {--count;}// 禁止拷贝和赋值,因为拷贝会增加实例,但这里我们不允许LimitedInstances(const LimitedInstances&) = delete;LimitedInstances& operator=(const LimitedInstances&) = delete;static int getCount() { return count; }private:static int count;static const int maxInstances = 5;  // 最大实例数
};int LimitedInstances::count = 0;

2.2 继承条件下的限制

// 基类限制派生类的实例数量
class Base {
protected:Base() {if (count >= maxInstances) {throw std::runtime_error("Too many instances");}++count;}~Base() {--count;}// 允许移动语义,但同样要控制数量?实际上移动构造不会增加计数,因为它是从现有对象构造,但我们这里禁止拷贝和移动Base(const Base&) = delete;Base(Base&&) = delete;Base& operator=(const Base&) = delete;Base& operator=(Base&&) = delete;private:static int count;static const int maxInstances = 10;
};int Base::count = 0;class Derived : public Base {// 派生类会调用Base的构造函数,因此受Base的计数限制
};

2.3 使用代理控制构造

// 通过代理类控制实例创建
class InstanceController;class LimitedClass {
private:LimitedClass() = default;  // 私有构造函数// 友元类,允许代理访问私有构造函数friend class InstanceController;
};class InstanceController {
public:LimitedClass& createInstance() {if (count >= maxInstances) {throw std::runtime_error("Too many instances");}++count;// 使用智能指针管理,这里简单返回静态实例的引用,实际可能需要更复杂的逻辑static LimitedClass instance;  // 注意:这里只是示例,实际可能需要多个实例return instance;}void releaseInstance() {--count;// 如果需要管理多个实例,则需要更复杂的逻辑}private:static int count;static const int maxInstances = 3;
};int InstanceController::count = 0;

⚖️ 3. 解决方案与最佳实践

3.1 单例模式的变体

// 带生命期控制的单例
template<typename T>
class Singleton {
public:static T& getInstance() {if (!instance) {instance = new T();}return *instance;}// 允许手动销毁单例,注意线程安全和重复销毁问题static void destroyInstance() {delete instance;instance = nullptr;}protected:Singleton() = default;virtual ~Singleton() = default;// 禁止拷贝和移动Singleton(const Singleton&) = delete;Singleton(Singleton&&) = delete;Singleton& operator=(const Singleton&) = delete;Singleton& operator=(Singleton&&) = delete;private:static T* instance;
};template<typename T>
T* Singleton<T>::instance = nullptr;// 使用示例
class MyClass : public Singleton<MyClass> {friend class Singleton<MyClass>;  // 允许Singleton访问MyClass的私有构造函数
private:MyClass() = default;
};

3.2 对象计数与异常安全

// 使用RAII管理对象计数
class InstanceCounter {
public:explicit InstanceCounter(int max) : maxInstances(max) {if (count >= maxInstances) {throw std::runtime_error("Too many instances");}++count;}~InstanceCounter() {--count;}static int getCount() { return count; }// 禁止拷贝和移动InstanceCounter(const InstanceCounter&) = delete;InstanceCounter(InstanceCounter&&) = delete;InstanceCounter& operator=(const InstanceCounter&) = delete;InstanceCounter& operator=(InstanceCounter&&) = delete;private:static int count;const int maxInstances;
};int InstanceCounter::count = 0;// 在需要限制的类中使用
class Limited {
public:Limited() : counter(5) {}  // 最多5个实例private:InstanceCounter counter;
};

3.3 使用std::unique_ptr管理有限实例

// 对象池模式
template<typename T, int MaxInstances>
class ObjectPool {
public:template<typename... Args>static std::unique_ptr<T, void(*)(T*)> acquire(Args&&... args) {if (count >= MaxInstances) {throw std::runtime_error("Too many instances");}++count;// 自定义删除器,在释放时减少计数return std::unique_ptr<T, void(*)(T*)>(new T(std::forward<Args>(args)...), [](T* ptr) {delete ptr;--count;});}static int getCount() { return count; }private:static std::atomic<int> count;  // 多线程安全
};template<typename T, int MaxInstances>
std::atomic<int> ObjectPool<T, MaxInstances>::count(0);// 使用示例
class ExpensiveResource {
public:ExpensiveResource() { /* 占用大量资源的操作 */ }void use() { /* 使用资源 */ }
};void useResource() {auto resource = ObjectPool<ExpensiveResource, 10>::acquire();resource->use();// 当resource离开作用域,自动释放并减少计数
}

3.4 线程安全的实例计数

// 使用原子操作和互斥锁确保线程安全
class ThreadSafeLimited {
public:ThreadSafeLimited() {std::lock_guard<std::mutex> lock(mutex);if (count >= maxInstances) {throw std::runtime_error("Too many instances");}++count;}~ThreadSafeLimited() {std::lock_guard<std::mutex> lock(mutex);--count;}// 禁止拷贝和移动ThreadSafeLimited(const ThreadSafeLimited&) = delete;ThreadSafeLimited(ThreadSafeLimited&&) = delete;ThreadSafeLimited& operator=(const ThreadSafeLimited&) = delete;ThreadSafeLimited& operator=(ThreadSafeLimited&&) = delete;static int getCount() {std::lock_guard<std::mutex> lock(mutex);return count;}private:static std::atomic<int> count;static const int maxInstances = 5;static std::mutex mutex;
};std::atomic<int> ThreadSafeLimited::count(0);
std::mutex ThreadSafeLimited::mutex;

💡 关键实践原则

  1. 明确限制策略
    在设计时决定是单例还是有限实例,以及如何处理边界情况(如超过限制时抛出异常还是返回nullptr)
  2. 考虑所有权和生命周期
    使用智能指针管理实例,确保异常安全且避免内存泄漏
  3. 线程安全是关键
    多线程环境下,必须使用原子操作或互斥锁保护计数变量
  4. 防止拷贝和移动
    删除拷贝构造函数和赋值操作符,避免意外创建新实例

对象数量限制模式选择

// 策略模式选择限制方式
template<typename T, template<typename> class CountingPolicy = SimpleCounting>
class LimitedObject : private CountingPolicy<T> {
public:template<typename... Args>LimitedObject(Args&&... args) : CountingPolicy<T>(std::forward<Args>(args)...) {CountingPolicy<T>::increment();  // 策略增加计数}~LimitedObject() {CountingPolicy<T>::decrement();}// 其他接口...
};// 计数策略
template<typename T>
class SimpleCounting {
protected:void increment() {if (++count > maxCount) {throw std::runtime_error("Too many instances");}}void decrement() {--count;}private:static int count;static const int maxCount = 1;  // 默认为单例
};template<typename T>
int SimpleCounting<T>::count = 0;

单例模式的线程安全实现(C++11之后)

// Meyer's Singleton: C++11保证静态局部变量初始化线程安全
class MeyerSingleton {
public:static MeyerSingleton& getInstance() {static MeyerSingleton instance;return instance;}// 删除拷贝和移动MeyerSingleton(const MeyerSingleton&) = delete;MeyerSingleton(MeyerSingleton&&) = delete;MeyerSingleton& operator=(const MeyerSingleton&) = delete;MeyerSingleton& operator=(MeyerSingleton&&) = delete;private:MeyerSingleton() = default;~MeyerSingleton() = default;
};

总结
限制类的对象数量是一种重要的设计模式,用于控制资源使用和确保系统约束。实现时需考虑实例计数、线程安全、生命周期管理和拷贝控制。

关键实现技术包括:静态计数、私有构造函数、删除拷贝和移动操作、智能指针管理,以及线程同步机制。根据需求选择单例模式或有限实例模式,并确保设计的一致性和安全性。

在现代C++中,利用RAII、智能指针和线程安全原语可以构建健壮的对象数量限制机制,从而提升代码的可靠性和可维护性。


文章转载自:

http://cFP9TYpr.jLmrx.cn
http://bDAQNz8W.jLmrx.cn
http://OHB41yoC.jLmrx.cn
http://KMelCfLn.jLmrx.cn
http://f6Fe17Sm.jLmrx.cn
http://YaCNeDRt.jLmrx.cn
http://8qxLSmVM.jLmrx.cn
http://nVYTZEib.jLmrx.cn
http://qh9Z2Dzv.jLmrx.cn
http://0UW9c7t4.jLmrx.cn
http://knYSOHjk.jLmrx.cn
http://c0m06SFs.jLmrx.cn
http://ztBNykdt.jLmrx.cn
http://vDdMPLnS.jLmrx.cn
http://4BtB5Wo2.jLmrx.cn
http://5Hvcaf7n.jLmrx.cn
http://s16raIPZ.jLmrx.cn
http://r0NrQlLY.jLmrx.cn
http://9Vc6SRNw.jLmrx.cn
http://PVaPGMdH.jLmrx.cn
http://zwWv9hBZ.jLmrx.cn
http://jS5WGf5w.jLmrx.cn
http://pK83Ouns.jLmrx.cn
http://zJu4IVvU.jLmrx.cn
http://1BOXYyOy.jLmrx.cn
http://w76fIopT.jLmrx.cn
http://Q3zVVM4A.jLmrx.cn
http://Lm2TTPkM.jLmrx.cn
http://w809aD5k.jLmrx.cn
http://NccOGItA.jLmrx.cn
http://www.dtcms.com/a/365866.html

相关文章:

  • MySQL 第十章:创建和管理表全攻略(基础操作 + 企业规范 + 8.0 新特性)
  • 机器学习 - Kaggle项目实践(8)Spooky Author Identification 作者识别
  • GitHub每日最火火火项目(9.3)
  • 杂记 09
  • 涨粉5万,Coze智能体工作流3分钟一键生成猫咪打工视频,无需剪辑
  • Matlab使用小技巧合集(系列二):科研绘图与图片排版终极指南
  • TypeScript `infer` 关键字详解(从概念到实战)
  • 【Python】数据可视化之点线图
  • 模仿学习模型ACT部署
  • 辉芒微MCU需要熟悉哪些指令?这15条核心指令与入门要点必须掌握
  • Linux gzip 命令详解:从基础到高级用法
  • Python基础(①①Ctypes)
  • C 内存对齐踩坑记录
  • 【随手记】vscode中C语言满足KR风格的方法
  • Elasticsearch核心数据类型
  • 深度学习——卷积神经网络
  • AI产品经理面试宝典第84天:RAG系统架构设计与优化策略面试指南
  • 分布式AI算力系统番外篇-----超体的现世《星核》
  • 【Doris入门】Doris数据表模型使用指南:核心注意事项与实践
  • 从PkiAsn1Decode函数到ASN1Dec_SignedDataWithBlobs函数
  • 中山AI搜索优化实践:技术干货解析与金拓智能案例
  • select, poll, epoll
  • 【108】基于51单片机智能输液监测系统【Proteus仿真+Keil程序+报告+原理图】
  • 详尽 | Deeplabv3+结构理解
  • CSS中使用 HSL(Hue, Saturation, Lightness) 动态生成色值
  • 二叉树结尾——销毁,层序遍历与判断完全二叉树
  • python如何解决html格式不规范问题
  • windows系统服务器测试部署springboot+vue+mysql项目
  • 使用 Acme.sh 获取和管理免费 SSL 证书
  • vue2头部布局示例