13

how to count the number of objects created in c++

pls explain with a simple example

Arunachalam
  • 5,417
  • 20
  • 52
  • 80

6 Answers6

33

Create template class with a static counter.

Each object in your application would then extend this template class.

When constructor is called increment static count (static variable is per class - shared by all objects of that class).

For example see Object Counter using Curiously recurring template pattern:

 template <typename T>
    struct counter
    {
        counter()
        {
            objects_created++;
            objects_alive++;
        }

        counter(const counter&)
        {
             objects_created++;
             objects_alive++;
        }   

    protected:
        virtual ~counter()
        {
            --objects_alive;
        }
        static int objects_created;
        static int objects_alive;
    };
    template <typename T> int counter<T>::objects_created( 0 );
    template <typename T> int counter<T>::objects_alive( 0 );

    class X : counter<X>
    {
        // ...
    };

    class Y : counter<Y>
    {
        // ...
    };

Usage for completeness:

    int main()
    {
        X x1;

        {
            X x2;
            X x3;
            X x4;
            X x5;
            Y y1;
            Y y2;
        }   // objects gone

        Y y3;

        cout << "created: "
             << " X:" << counter<X>::objects_created
             << " Y:" << counter<Y>::objects_created  //well done
             << endl;

        cout << "alive: "
             << " X:" << counter<X>::objects_alive
             << " Y:" << counter<Y>::objects_alive
             << endl;
    }

Output:

created:  X:5 Y:3
alive:  X:1 Y:1
Ghita
  • 4,465
  • 4
  • 42
  • 69
stefanB
  • 77,323
  • 27
  • 116
  • 141
  • Hi. Nice approach. I never knew about that. Thanks! – bdhar Dec 18 '09 at 06:19
  • Some time ago I was doing some static polymorphism and bumped to this example, I really like it, and static polymorphism is cool as well ... – stefanB Dec 18 '09 at 06:21
  • Nice solution, I have a doubt though.. is it really necessary to make the destructor virtual in the class template when using CRTP? I am just worried about the slight size overhead caused by the v-tables.. – Naveen Dec 18 '09 at 06:39
  • its due to private inheritance since in this case derived class object is not base class one and compiler will not do implicit type conversion. – Ashish Dec 18 '09 at 08:04
  • is there any other reason for the private inheritance? – Mizipzor Dec 18 '09 at 08:09
  • 3
    how does this handle. X x2; X x3 = x2; – Jagannath Dec 18 '09 at 08:27
  • 1
    I think there is no need to make destructor virtual and benefits of private inheritance are : 1. counter *px = new X; // error no implicit conversion is allowed 2. delete px; // destructor not accessible – Ashish Dec 18 '09 at 11:05
  • struct inheritance is public by default, since it's not specified it's public not private, unlike class where the inheritance is public by default. – stefanB Dec 18 '09 at 12:24
  • Unfortunately, this example only counts the objects created that are derived from the template class. – Thomas Matthews Dec 18 '09 at 18:06
  • you could implement static count in each of your classes by hand, but this simplifies things a bit, you can add custom stuff in classes that need to do more ... – stefanB Dec 19 '09 at 12:01
  • In normal case, if I try to access static member from constructor we get error message right. So is that is the reason we have to go for template? – Rajesh Sep 15 '17 at 09:50
  • Virtual destructor of counter may increase the size of derived class, because of virtual table. Destructor of counter can be protected, to prevent it from being deleted by pointer of counter. – where23 Jun 29 '18 at 02:35
  • Edited the counter, mainly, to include copy ctor counting. Without it the derived class implicitly could have called the compiler generated counter version and copies would have been lost. – Ghita Oct 18 '19 at 12:27
  • @stefanB error: 'objects_created' is a protected member of 'counter', error: 'objects_alive' is a protected member of 'counter' – NaturalDemon Sep 30 '20 at 15:54
12
template <class T>
class Counter
{
  private:
      static int count;
  public:
    Counter()
    {
       count++;
    }  
    Counter(const Counter &c)
    {
       count++;
    }   
    ~Counter()
    {
       count--;
    }    
    static int GetCount() {

         return count;
    }
}

template<class T> 
int Counter<T>::count = 0; 



class MyClass : private Counter<MyClass>
{
   public:
      using Counter<MyClass>::GetCount;
}

This technique is called CRTP

Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
Ashish
  • 8,441
  • 12
  • 55
  • 92
  • 3
    @stefanB, This is the correct approach. You need to have copy constructor in Counter. – Jagannath Dec 18 '09 at 08:35
  • 1
    +1, stefanB's approach does not handle 'X x2; X x3 = x2;'. But you can't initialize count like that, since it's not const. – KeatsPeeks Dec 30 '09 at 18:52
4

Number of objects for what? If you want to count the number of objects of a specific class, you can use a static counter. Something like below.. Increment counter on creation and decrement while destruction..

class A
{
  public:
    static int counter;
    A()
    {
      counter ++;
    }
    virtual ~A()
    {
      counter --;
    }
};

int A :: counter = 0;
bdhar
  • 21,619
  • 17
  • 70
  • 86
  • How do you keep track if the object is created using malloc? – Kranthi Kumar Apr 14 '13 at 18:04
  • @KranthiKumar It *isn't* 'created by `malloc()`.' It is *allocated* statically, or by `new`, or on the stack; it is *constructed* by one of its constructors; and it is destroyed by its destructor. – user207421 Mar 11 '15 at 09:03
4

You have to overload the new and delete operators to count memory allocations.

void * operator new (size_t size)
{
    void * p = malloc (size);
    num_allocations++;
    return p;
}

void operator delete (void * p)
{
    num_deletions++;
    free (p);
}
DevDevDev
  • 5,107
  • 7
  • 55
  • 87
  • I think new [] and delete [] also have to be overloaded if you want to track objects on heap . – Ashish Dec 18 '09 at 08:11
  • Yes you are correct Mac. I was just trying to get him started. You need to overload every variation of new that you are using. – DevDevDev Dec 19 '09 at 00:25
  • doesnt that break the code? delete should call destructor first; – NoSenseEtAl Sep 14 '11 at 12:22
  • I think there is not need to overload the `new` / `delete` operators because AFAIK the `new` operator invokes the object's constructor and the corresponding call to delete invokes the object's destructor. – Amer Sawan Nov 16 '15 at 17:52
  • @DevDevDev if you use the default constructor / destructor of a class, the "new / delete operators" are not being executed – NaturalDemon Sep 30 '20 at 18:01
0

You could create a counter variable into the public: of your class (assuming here you're talking about counting objects from a class you created)

class Widget {
public:
    Widget() { ++count; }
    Widget(const Widget&) { ++count; }
    ~Widget() { --count; }

    static size_t howMany()
    { return count; }

private:
    static size_t count;
};
// obligatory definition of count. This
// goes in an implementation file
size_t Widget::count = 0;

Taken from ddj.com

Alex Marcotte
  • 475
  • 3
  • 6
  • you should read the whole article from scott meyers to see that this solutions is not the best. At the end of the article he describes the template approach mentioned in the other posts. – codencandy Dec 18 '09 at 09:49
0

update on code as opposed to "stefanB" solution, some variables are in protected access mode and will not be accessible.

template <typename T>
    struct counter
    {
        counter()
        {
            std::cout << "object created"<< endl;
            this->objects_created++;
            this->objects_alive++;
        }

        counter(const counter& test)
        {
            std::cout << "object created:" << test << endl;
             this->objects_created++;
             this->objects_alive++;
        }

        static int getObjectsAlive(){
            return objects_alive;
        }

        static int getObjectsCreated(){
            return objects_created;
        }


    protected:
        virtual ~counter()
        {
            std::cout << "object destroyed"<< endl;
            --objects_alive;
        }
        static int objects_created;
        static int objects_alive;
    };
    template <typename T> int counter<T>::objects_created( 0 );
    template <typename T> int counter<T>::objects_alive( 0 );

    class X : counter<X>
    {
        // ...
    };

    class Y : counter<Y>
    {
        // ...
    };
    
    Usage for completeness:
    
        int main()
        {
            X x1;
        
            {
                X x2;
                X x3;
                X x4;
                X x5;
                Y y1;
                Y y2;
            }   // objects gone
        
            Y y3;
         
    cout << "created: "
         << " X:" << counter<X>::getObjectsCreated()
         << " Y:" << counter<Y>::getObjectsCreated()  //well done
         << endl;

    cout << "alive: "
         << " X:" << counter<X>::getObjectsAlive()
         << " Y:" << counter<Y>::getObjectsAlive()
         << endl;
        }
NaturalDemon
  • 934
  • 1
  • 9
  • 21