Sobes.tech
Middle+

How to limit the number of class instances in C++?

sobes.tech AI

Answer from AI

There are several methods, the main ones:

  1. Using a static counter variable:

    • Declare a static variable of type int to track the number of created instances.
    • Increment the counter in the constructor.
    • Decrement the counter in the destructor.
    • In the constructor, check the counter value and, if the limit is exceeded, throw an exception or take other actions.
    • Make the constructor private or protected, and create instances through a static factory function that performs the check.
    • Prohibit copying and moving.
    #include <iostream>
    #include <stdexcept>
    
    class LimitedInstances {
    private:
        static int instance_count;
        static const int max_instances = 3;
    
        LimitedInstances() {
            if (instance_count >= max_instances) {
                throw std::runtime_error("Maximum number of instances reached.");
            }
            instance_count++;
            std::cout << "Instance created. Total: " << instance_count << std::endl;
        }
    
        // Prohibit copying and moving
        LimitedInstances(const LimitedInstances&) = delete;
        LimitedInstances& operator=(const LimitedInstances&) = delete;
        LimitedInstances(LimitedInstances&&) = delete;
        LimitedInstances& operator=(LimitedInstances&&) = delete;
    
    public:
        ~LimitedInstances() {
            instance_count--;
            std::cout << "Instance destroyed. Total: " << instance_count << std::endl;
        }
    
        static LimitedInstances* create_instance() {
            return new LimitedInstances();
        }
    };
    
    int LimitedInstances::instance_count = 0;
    
  2. Using a modified Singleton pattern:

    • Usually, Singleton guarantees one instance. To limit the number of instances, it can be modified to manage access to creation via a static function and track created objects in a private static container (e.g., std::vector or std::list).
    #include <iostream>
    #include <vector>
    #include <stdexcept>
    
    class NLimitedInstances {
    private:
        static std::vector<NLimitedInstances*> instances;
        static const int max_instances = 2;
    
        NLimitedInstances() {
            std::cout << "NLimitedInstances created." << std::endl;
        }
    
        // Prohibit copying and moving
        NLimitedInstances(const NLimitedInstances&) = delete;
        NLimitedInstances& operator=(const NLimitedInstances&) = delete;
        NLimitedInstances(NLimitedInstances&&) = delete;
        NLimitedInstances& operator=(NLimitedInstances&&) = delete;
    
    public:
        static NLimitedInstances* get_instance() {
            if (instances.size() >= max_instances) {
                 throw std::runtime_error("Maximum number of NLimitedInstances reached.");
            }
            NLimitedInstances* new_instance = new NLimitedInstances();
            instances.push_back(new_instance);
            return new_instance;
        }
    
        static void destroy_instance(NLimitedInstances* instance) {
            // Find and remove the instance from the vector
            for (auto it = instances.begin(); it != instances.end(); ++it) {
                if (*it == instance) {
                    delete *it;
                    instances.erase(it);
                    std::cout << "NLimitedInstances destroyed." << std::endl;
                    return;
                }
            }
        }
    
        ~NLimitedInstances() = default; // or add cleanup logic
    };
    
    std::vector<NLimitedInstances*> NLimitedInstances::instances;
    

Both approaches require careful resource management, especially when using new. The modified Singleton pattern can be more complex to implement in terms of object destruction, especially if their lifecycle does not coincide with program termination.

The choice of method depends on specific requirements and system complexity. The static counter approach is generally simpler to understand and implement.