Solved

A question related to Copy Constructor

Posted on 2003-11-17
4
594 Views
Last Modified: 2008-03-03
I was just going thru Thinking in C++ and came across a confusing issue.
The below code demonstrates that

class A {
        static int i ;
public :
      A () {
        i++ ;
        cout << "Constructor" << endl ;
        j = 0 ;
       }
       ~A () {
         i-- ;
         cout << "Destructor" << endl ;
         print ( ) ;
       }
       static void print ( ) {
               cout << i << endl ;
       }      
};

A f (A temp ) {
       A::print ( ) ;
       return temp ;
}

int A::i = 0 ;

int main(int argc, char *argv[]) {

      {
            A a1 ;
            A::print() ;
            cout << "Before f () " << endl ;
            A a2 = f ( a1 ) ;
            cout << "After f () " << endl ;
            A::print() ;
      }      
    system("PAUSE");      
    return 0;
}


Now, the output above prints
Constructor
1
Before f()
1
Destructor
0
After f()
0
Destructor
-1
Destructor
-2


The book explains the above output in the following way

After a1 is created, the object count is one, which is fine. But after the call to f( ) you would expect to have an object count of two, because a2 is now in scope as well. Instead, the count is zero, which indicates something has gone horribly wrong. This is confirmed by the fact that the two destructors at the end make the object count go negative, something that should never happen.

Look at the point inside f( ), which occurs after the argument is passed by value. This means the original object a1 exists outside the function frame, and there’s an additional object inside the function frame, which is the copy that has been passed by value. However, the argument has been passed using C’s primitive notion of bitcopying, whereas the C++ HowMany class requires true initialization to maintain its integrity, so the default bitcopy fails to produce the desired effect.

When the local object goes out of scope at the end of the call to f( ), the destructor is called, which decrements objectCount, so outside the function, objectCount is zero. The creation of a2 is also performed using a bitcopy, so the constructor isn’t called there either, and when a1 and a2 go out of scope, their destructors cause
the negative values of objectCount.

My question========
I didn't get the fact that when u say that copy is happening as per C-style bit-copying, thus the constructor does not get called. OK, but then why does the destrcutor for that particular object gets called.....?? Also, is this not a loophole on part of C++, though I know that the solution to the above problem is using Copy-Constructors

Your comments are welcome

Thanks in advance

Amit
0
Comment
Question by:Sys_Prog
  • 2
4 Comments
 
LVL 11

Accepted Solution

by:
bcladd earned 50 total points
Comment Utility
Actually, a copy constructor IS being called. Granted, you didn't write one, but the compiler provided one when one was required but not provided. The ACTIVITY of the provided copy constructor was to call memcpy (copy the memory occupied by the original into the copy). So, though the effect is a simple struct assignment, a C++ copy constructor was called.

This behavior is often all you need (no static variables, no dynamic memory allocation). You can also get away without defining a default constructor (one is provided for you free of charge by the compiler if it is used) that will simply call default constructors for parent classes and class members; destructors are also provided if not defined.

Note that the three default implementations are public which may not be what you want. Thus to create a singleton (see a design patterns reference if necessary) the constructor and copy constructor are defined as protected and the body of the copy constructor is typically not provided (it is a conceptual error to make a copy of a singleton, something there should be only one of).

Hope this helps,
-bcl
0
 
LVL 10

Author Comment

by:Sys_Prog
Comment Utility
Hi bcladd,

I got the first two para's of whatever u said, could u please eloborate on the third para

Also, one more question regarding whatever u exaplined in the 1st 2 para's

As per my understanding OR whatever I have read of copy-constructor, a copy-constructor should  always have a argument of the same type by REFERNCE. But when the compiler does provide that copy constructor internally, does it consider this fact, I guess it would be considering

Thanks in advance

Amit
0
 
LVL 11

Expert Comment

by:bcladd
Comment Utility
(1) Singleton is a design pattern where you only want exactly one of an object instantiated, never two. Consider an object representing the error logging system in a game engine (gamedev.net has a series of articles on something called Enginuity that I am reading; example from part 2 of the article). You don't want two error loggers because each would have to have control of the same open files. So we don't want anyone copying our Elog object. The best way to accomplish that is to hide the copy constructor; the compiler will then not permit anyone to pass Elog by value or otherwise copy it. We also don't want anyone to create a new one so we hide the default constructor.

Typically, to make it so that a client of an object cannot do something we just don't define a function that does "that". Doesn't work for copy or default constructors because the compiler will provide one silently when it is called.

(2) The provided copy constructor looks something like this (this is a simplified approximation):

Copyless::Copyless(const Copyless & original) {
    memcpy(this, &original, sizeof(*this);
}

Hope this helps, -bcl
0
 
LVL 9

Assisted Solution

by:_ys_
_ys_ earned 50 total points
Comment Utility
>but then why does the destrcutor for that particular object gets called.....??
Don't think bcladd covered this part.

By now you should be accepting of the fact that the compiler has synthesised a copy constructor on your behalf, and called it appropriately. And because you didn't write it, i++ never happened.

I'm also hoping you understand the concept of constructor overloading - and that you can have multiple constructors defined.

But, you can only ever have one (and only one) destructor. It cannot be overloaded, and it does not return a value either. Incidentally you _must_ have a destructor. If you don't provide one the compiler synthesises this for you as well.

As you can only have one, it will be called. Thus i-- will get executed. The fact that it used the synthesised copy constructor to create the instance is irrelevant. It still needs to invoke a destructor.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
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 goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

744 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now