Solved

Reuse of a pointer ??

Posted on 2003-11-20
7
749 Views
Last Modified: 2008-03-06
Hello...

I am playing with the following code at the minute, after reading something similar in a textbook of mine.  Let me first show you the code:

/////////////////////////////////////

#include <iostream>

using std::cout;
using std::endl;

class Test
{
public:
      Test() { count++; }
      ~Test() { count--; cout << count << endl; }
      Test(const Test&) { cout << "Copying" << endl; }
      static int count;
};

int Test::count = 0;

int main()
{
      Test a[10];
      Test* t = 0;
      for (int i = 0; i < 10; i++) {
            t = new Test();
            a[i] = *t;
            delete t;
      }
      cout << Test::count << endl;
      //delete[] a;
      return 0;
}

/////////////////////////////////////

Nice and simple.  Now, I have declared a pointer to an instance of my Test class, t, and am setting that up to point to 10 objects that will be created in a loop.  Right.  Now first of all, I do not understand how the pointer t can point to 10 different objects when it is being (what I perceive as) reassigned by the statement

t = new Test();

So firstly, why is this ?  The book I am reading says 'a copy of the object is placed into the array a', hence that is why we 'delete t', but I have wrote a copy constructor and there is no evidence of it being called !

Secondly, I put the static variable in as a count of how many objects are being created, and it appears that my book is correct; when I do not have the 'delete t' statement the output from

cout << Test::count << endl

is 20; when I do have it the output is 10.  So with this info, I decided I had better delete the contents of my array 'a', so proceeded to call 'delete [] a', to which VC++ replied:

warning C4154: deletion of an array expression; conversion to pointer supplied

Eh ?!?!

I then realised that there is no reason to delete this array, as I have not allocated space with 'new' for it.  But the output (as stated above) is:

20
19
18
17
16
15
14
13
12
11
10

meaning 10 items are still left undestroyed.  So, why does 'delete[] a' give the warning (and crash the program on running if I ignore it), and how can I delete the objects left over ?

Cheers in advance.
0
Comment
Question by:mrwad99
7 Comments
 
LVL 11

Expert Comment

by:bcladd
ID: 9788287
Note you have an array of OBJECTS. They will go out of scope AUTOMATICALLY when the funciton where they are declared terminates. Since they are declared in main(), the program, too, will terminate when main finishes.

Variables declared locally in functions have what is called automatic storage. An object will go out of scope and have its destructor called when the function returns.

Try instrumenting the destructor. You'll see it called ten times after the last executable line in main (as well as once for each call to delete).

Each call to new allocates a new object on the heap. These objects are NOT automatically deleted. This is good since you can keep dynamically allocated objects around between calls to functions. It is bad because it requires the user to handle the deletion (this is the source of many memory leaks).

Hope this helps, -bcl
0
 
LVL 11

Expert Comment

by:bcladd
ID: 9788345
Note that you should increment count in the copy constructor, too, since it is called when things are created and the count will be wrong if it is not incremented in all constructors.

-bcl
0
 
LVL 11

Accepted Solution

by:
bcladd earned 30 total points
ID: 9788392
Sorry, I missed the main point of your question: The copy constructor is NOT called because you assign *t to an element in the array. This calls operator=, not the copy constructor. If you don't write an assigment operator
one is synthesized for you. Try adding the following to your class:

  Test & operator=(const Test & lhs) {
    if (this != &lhs) {
      cout << "Assigning" << endl;
    }
    return *this;
  }

And you'll see the assignments take place (you can print out (unsigned int) this to see the address of each object if you want to match up assignments and destructions and constructors and stuff).

-bcl
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
LVL 17

Assisted Solution

by:rstaveley
rstaveley earned 20 total points
ID: 9788910
> Now first of all, I do not understand how the pointer t can point to 10 different objects when it is being (what I perceive as) reassigned by the statement

A pointer is simply something that points to something. The new operator instantiates an instance of T and the pointer t is made to point to that instance by the assignment '='. The delete operator then deletes that instance and immediately subsequent to the deletion, the pointer is left pointing to a chunk of memory that belongs to nobody.

> The book I am reading says 'a copy of the object is placed into the array a', hence that is why we 'delete t', but I have wrote a copy constructor and there is no evidence of it being called !

The copy is made in the the terse line of code...

    a[i] = *t;

The * operator makes you refer to the chunk of memory now being pointed to by t. The index [i] makes you refer to the object in the static array at index i. That innocent looking assignment does a lot of work. It copies the contents of the newly created instance of Test pointed to by t and loads it into the array at the position indexed by i.
               
> So with this info, I decided I had better delete the contents of my array 'a', so proceeded to call 'delete [] a',

You only need to delete dynamically allocated objects (otherwise known as objects created from the free store or heap). When an object is automatically created (a local variable created on the stack), it's destructor is automatically called when the object goes out of scope (i.e. the function is exited). Similarly static ojects have their destructors called when the program exits.

Here's an illustration:
--------8<--------
#include <iostream>

class X {
const char *p;
public:
    X(const char *p = "Anonymous") : p(p) {}
    ~X() {std::cout << "Destructor for " << p << " called\n";}
};

X staticX("Static");

int main()
{        
        X *dynamicX = new X("Dynamic");

        std::cout << "Entering scope...\n";

        { // A local scope
                X automaticX("Automatic");
                X arrayx[3];
        }

        std::cout << "...Exited scope\n";
        delete dynamicX;
        std::cout << "...Exiting program\n";
}
--------8<--------
0
 
LVL 9

Expert Comment

by:_ys_
ID: 9789872
With the presence of:

delete t;

I can't believe that your ouput is
>20
>19
>...
>10

Can someone verify this.

[ ... not having access to a compiler really sucks]
0
 
LVL 11

Expert Comment

by:bcladd
ID: 9790028
I can get the output in the original post if I comment out the delete call. I would guess that it is from one of the test runs where delete t was NOT funcitonal.

-bcl
0
 
LVL 19

Author Comment

by:mrwad99
ID: 9790126
Right then:

As _ys_ states, the output given *was* when 'delete p' was commented out.

I am forgetting that the statement

Test a[10];

Results in the default constructor being called ten times, hence creating 10 objects (never).  I was getting confused thinking "how the heck is the assignment operator copying the object; should that not be the copy constructor"... but in fact I know now that the *object itself* was not being copied, only the values of it. Hence the values of the object pointed to by p were assigned to the values of the objects *already there* that were created by the default constructor (I say values; I changed the code locally to allow the constructor to take an int parameter just to test).

The penny drops !

I have thus split the points between rstavely and bcladd for their combined answer.

Many thanks to all once again !
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
C language IDE – Compilers installation 14 75
How to gracefully close the c++ 11 thread? 3 109
Copy output image from TWindowsMediaPlayer 6 48
Outlook 13 45
Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

808 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question