Question

I'm trying to dynamically allocate (it's not so dynamic as it is right now, but eventually it will be) memory for objects in a very simple C++ program. I'm new to classes and have only recently started playing with C++, leaving C behind. Here's the code:

#include <iostream>
using namespace std;

class Test {
  private:
    int i;
  public:
    Test(int);
    ~Test();
    void print();
};

Test::Test(int ii) { i = ii; }
Test::~Test() { i=0; cout << "deconstructor called...value of i= " << i << endl; }
void Test::print() { cout << "value of i= " << i << endl; }

int main()
{
  Test a(10),*b,*c;
  //a.print(); // this works

  b = new Test(12);
  //b->print(); // this works as well

  for (int i=0; i<2; i++)
    c = new Test(i);

  c->print(); /* this shows that the value of i=1 .. should be 0? */
  c[0].print(); /* as expected (I guess), this prints i=1 as well... [expected because c->print() shows i=1 also */
  c[1].print(); /* shows value of i=0... */

  //delete []c; /* this fails miserably, but `delete c` works, why :( */

}

A lot of my confusion is actually included within comments in the code itself. I'm basically trying to have an array c where each element of the array is an object of itself.

The behavior of the code that I'm getting is described in the comments.

Was it helpful?

Solution

Perhaps we should look at the declarations, expanded you have:

Test a(10);
Test *b;
Test *c;

You have defined b and c as pointer-to-Test, but you seem to want c to be an array of pointer-to-test. The declaration for c you intended was likely:

Test **c;

which you would initialize:

c = new Test*[2];

for (int i=0; i<2; i++)
   c[i] = new Test(i);

and which you would access thus:

c[0]->print();
c[1]->print();

OTHER TIPS

There are few serious problems with the given code.

  1. Performing new on *b but missed to delete it.
  2. You are overwriting *c few times in for loop, which will leak memory. Always deallocate resources before allocating a new one from a pointer.
  3. If you are allocating with new/new[]/malloc then you must deallocate the pointer with delete/delete[]/free respectively. The same you are not maintaining with *c (that's why it fails).

Also, apart from learning dynamic allocation one should also be aware of STL containers, which provide a better way of handling dynamic resources. e.g. std::vector.

for (int i=0; i<2; i++)
    c = new Test(i);

The above code leaks the memory. c just point to the lastly constructed object in the loop iteration.

c->print(); /* this shows that the value of i=1 .. should be 0?

Here c points to location constructed on new Test(1);. So, the output.

Every new[] should be accompanied with delete[] and new with delete. You cannot intermix both.

That the delete[] doesn't work is perfectly normal: you never allocated c as an array, but as a pointer. You could store the address of an array in a pointer, but that's all. I'm actually wondering why exactly c[1] works, because your for loop just stores repeatedly pointers to newly allocated objects in the same pointer (you are not populating an array!).

delete c[]; Only deletes starting element. If you want to delete that array use dz delete c[] in for loop

You failed to allocate memory for c and keep on coding its wrong how can you get a output without allocating memory to a pointer variable?

See according to me , you have allocated memory for *c multiple times as

for (int i=0; i<2; i++)
c = new Test(i);

Have a look on this code, which will make everything clear

for (int i=0; i<2; i++)
{   c = new Test(i);    }       /*see , here the loop goes for i=0; then
                                for i=1; which basically overwrites what c will have
                                 i.e. finally       c = new test(1); */
c->print(); /* works fine , gives value of i=1 */
c[0].print(); /* as expected , this prints i=1 as well... */
c[1].print(); /*clearly, it will give a garbage value */
delete c;

But According to me , it would be more fine to replace

for (int i=0; i<2; i++)
{   c = new Test(i);    }

with

c = new Test(1);    //as the previous code is doing the same in for loop but that was consuming more resources

So if you want output as i=0 and then i=1 then do so-

c = new int(0);
c->print(); /* works fine , gives value of i=0 */
c[0].print(); /* as expected , this prints i=0 as well... */
delete c;

c = new int(1);
c->print(); /* works fine , gives value of i=1 */
c[0].print(); /* as expected , this prints i=1 as well... */
delete c;

The above code is what which will completely satisfy your need.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top