A question related to Copy Constructor

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() ;
    return 0;

Now, the output above prints
Before f()
After f()

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

LVL 10
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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,

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Sys_ProgAuthor Commented:
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

(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
>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.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.