Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

calling copy constructor

Posted on 1999-07-03
18
Medium Priority
?
226 Views
Last Modified: 2010-04-02
     Hi. I have a stack program.

      In my driver, I have 2 stacks of ints, Y and S. Both have 6 elements. When I assign:

                              S = Y;

     the overloaded operator works fine and S ends up  the same as Y.
       But, when I try to call the copy constructor, I get an error.  
        I comment out the //S =Y assignment and try this:

        S(Y);   ?????   //Isn't this the correct way to call a copy constructor?
       Shouldn't this do the same thing as the overloaded assignment? .

       Doesn't an assignment implicitly call a copy constructor?

       If so, and I have both the regular copy constructor and the overloaded assignment
       which one is used by the compiler?
 
               
  ***********deep copy constructor**************

       template <class ItemType>
         StackType<ItemType>::StackType(const StackType<ItemType>& Y)
         {
            if(Y.Top > Size)
            {

               delete[]data;  
               data = new ItemType [Y.Size];

            }
         
               for(int i =0; i<=Y.Top; i++)
                  {  
                     Y.data[i] = data[i];
                  }
                     Size = Y.Size;
                     Top = Y.Top;
      }

      *********overloaded assignment operator**************
         *****works fine*******

         template <class ItemType>
         StackType<ItemType>& StackType<ItemType>::operator=(const    StackType<ItemType> & Y)
         {
            if(Y.Top > Size)
            {
               if(this == &Y)
               {
                  return *this;
               }

               delete[]data;  
               data = new ItemType [Y.Size];

            }
         
               for(int i =0; i<=Y.Top; i++)
                  {  
                     Y.data[i] = data[i];
                  }
                     Size = Y.Size;
                     Top = Y.Top;

                  return *this;
         }






0
Comment
Question by:rdf
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
  • 4
  • +2
18 Comments
 

Author Comment

by:rdf
ID: 1199076
forgot to say thanks :)
0
 
LVL 5

Expert Comment

by:yonat
ID: 1199077
> S(Y);   ?????   //Isn't this the correct way to call a copy constructor?

Only if this is in a declaration:
    StackType<SomeType> S(Y);

> Doesn't an assignment implicitly call a copy constructor?

Again, only in declarations:
    StackType<SomeType> S = Y;

0
 

Author Comment

by:rdf
ID: 1199078
Yonat, I declare StackType<int>S(Y);

Then, when I call with: S(Y);, I get an error saying "( ) bad operands"
Also, if I try to construct a T before the above declaration, it is a double declaration, again resulting in an error.  How do I avoid this?
thanks
rdf
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

Accepted Solution

by:
apmontgo earned 80 total points
ID: 1199079
Rdf-
   You cannot explicitly call a copy constructor unless it is in the declaration or CONSTRUCTION of the  variable. If you could call a copy constructor at any old time in a program, it would be an assignment and not the initial construction. In order to call the copy constructor for S you would code:
stack<int> S(Y);
   also, you asked if assignment operators inherently called copy constructors. This is a common misconception and a cause of major errors in C++. The assignment operator is much different from a copy constructor since it has to properly get rid of the current data. Many people consider copy constructors and assignment operators synonomus. and this is a common cause of memory leaks with classes containing dynamically allocated data. They're not the same.
0
 
LVL 5

Expert Comment

by:yonat
ID: 1199080
> I declare StackType<int>S(Y);

Then S should now be a copy of Y.

> Then, when I call with: S(Y);

Why do you need to make this call? If you want to copy Y into S again, you can now do
    S = Y;

I am not sure I understand what you are trying to do. Are you talking about calling the copy constructor from within the assignment operator implementation? If so, a common idiom is to have a private member function copy(StackType<T> rhs) and call this function from both the copy constuctor and the assignment operator.

For example:

template <class ItemType>
StackType<ItemType>::copy(StackType<T> rhs)
{
    if(Y.Top > Size)
    {
        delete[]data;    
        data = new ItemType [Y.Size];
    }
                             
    for(int i =0; i<=Y.Top; i++)
    {    
        Y.data[i] = data[i];
    }
    Size = Y.Size;
    Top = Y.Top;
}

template <class ItemType>
StackType<ItemType>::StackType(const StackType<ItemType>& Y)
{
    copy(Y);
}

template <class ItemType>
StackType<ItemType>::operator=(const StackType<ItemType> & Y)
{
    if (this != &Y)
        copy(Y);
    return *this;
}
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 1199081
The copy constructor should properly initialise the member variables, otherwise you are likely to end up with crashes and/or memory corruption,  the copy constructor definition should look like:

template <class ItemType>
StackType<ItemType>::StackType(const StackType<ItemType>& Y)
  : data(0), Size(0)
{
  ... rest as before...
}

I agree with most of what else has been said, you seem to be confusing the copy constructor with something else, the copy constructor is just a constructor (i.e. it initialises the state of a new object) with values that come from another object of the same type.

The special things about a copy constructor are nothing to do with its basic purpose, they are to do with:

i) the compiler will provide a copy constructor if you don't provide one.
ii) the compiler can make assumptions that the copy constructor actually does what it is supposed to (that is it does copy the state of one object to a new one).
         


0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 1199082
Copy constructors are called in several instances:

let's say we wrote some class called MyClass..

1. When we construct a new object from an old one:
   MyClass new_object(existing_object);
   or equivalently
   MyClass new_object = existing_object;
   but NOT
   MyClass new_object;
   new_object = existing_object;  // this is assignment

2. When you pass by value.. passing by value means the program makes a copy of the object, which means that the copy constructor is called implicitly.

Can anyone think of any more?? I think there might be one more case, but I don't remember.
0
 
LVL 2

Expert Comment

by:VEngineer
ID: 1199083
Copy constructors are called in several instances:

let's say we wrote some class called MyClass..

1. When we construct a new object from an old one:
   MyClass new_object(existing_object);
   or equivalently
   MyClass new_object = existing_object;
   but NOT
   MyClass new_object;
   new_object = existing_object;  // this is assignment

2. When you pass by value.. passing by value means the program makes a copy of the object, which means that the copy constructor is called implicitly.

Can anyone think of any more?? I think there might be one more case, but I don't remember.
0
 
LVL 2

Expert Comment

by:VEngineer
ID: 1199084
Return values, i.e.

Obj X::Func()
{
    Obj a;
    // do something

    return a;  // calls copy constructor
}

although this is the case where the compiler makes its assumption, the compiler is allowed to optimise away this call to the copy constructor (called return value optimisation), because the compiler can assume that the state of the returned object will be the same as the state of the object constructed in the function.
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 1199085
I think the system has gone a little screwy, the comment about return values was posted by me, jasonclarke, but on my browser it says it was posted by VEngineer.
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 1199086
Thanks everyone,
I use my overloaded assignment to assign S to Y. I do some things to the stacks, push and pop and empty and clear. Then I push an Item onto the stack of both S and Y.
So, at this point I have a stack of size one integer for both S and Y.
I now want to copy Y into T, via the copy constructor, then print out T.

I use this:***StackType<int>T(Y);
                  outfile<<T<<endl;
                  outfile<<Y<<endl;

When I print, T has zero as its lone element, and so does Y. Why will Y's one element, which is 9, not be copied into T?

I just want to prove that the copy constructor works.
0
 

Author Comment

by:rdf
ID: 1199087
yonat here (in case the comments get mixed up again).

Are you sure Y contains an element before the copy constructor is called? Try:

    outfile<<Y<<endl;
    StackType<int>T(Y);
    outfile<<T<<endl;
    outfile<<Y<<endl;

just to make sure.
0
 
LVL 5

Expert Comment

by:yonat
ID: 1199088
Yes, outfile Y prints out its element, 95.
then, after the copy constructor is called, outfile T prints 0 and outfile Y prints 0
0
 

Author Comment

by:rdf
ID: 1199089
Yonat here.

In the copy constructor you have:
    for(int i =0; i<=Y.Top; i++)
    {
        Y.data[i] = data[i]; // here is the problem
    }

change the problematic line to:
        data[i] = Y.data[i];
0
 
LVL 5

Expert Comment

by:yonat
ID: 1199090
yonat, when I do that I get a bus error. I am beginning to think that having a overloaded assignment operator and a calling a copy constructor both is not a good idea. The overload works perfectly, and it is the same code as the copy constructor, barring the instance when both stacks reside at the same address.

rdf here
0
 

Author Comment

by:rdf
ID: 1199091
Is there a way to set the size of T before I try to copy Y into it?
For instance, is there some syntax such as:  
        **StackType<int>T(6), Y ***  ???????

rdf here
0
 

Author Comment

by:rdf
ID: 1199092
yonat here.

StackType<ItemType>::StackType(const StackType<ItemType>& Y) : Size(0)
{
... (same as before)

The notation
    : member(value)
initalizes member to value.
0
 
LVL 5

Expert Comment

by:yonat
ID: 1199093
I took out the **** if Y.Top > Size and also the delete data, that seems to have been the problem.
*******************************************
      data = new ItemType [Y.Size];
      for(int i=0; i<=Y.Top; ++I)
         {
         Y.data[i] = data [i];
         }
         Size = Y.Size;
         Top = Y.top;

Don't know who to give the points to, but I'll give them to apmontgo. Yonat, thanks for noticing I had the for loop assignment backwards :)
rdf
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
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 be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

721 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