TITLE: copy constructor and assignment basics (Newsgroups: comp.lang.c++, 24 Feb 98) ANDY: "Andy" > > I'm a beginner to C++ and I have a question which can't be answered by my > > reference book. I see from my book that copy constructor and overloaded > > = operator do almost the same things. What's the difference between them > > and if they do the same thing, why not to use only one? Plus, can I call > > the copy constructor as a function in the overloaded = operator function? FLONES: Arne W Flones > James O. Coplien's "Advanced C++ Programming Styles and Idioms" has > the best description of copy constructors I've seen. If you want to > understand C++ techniques you might want to check a copy out at your > local library. Highly recommended for the person who wants to go > beyond the newbie stage. > HOPPS: "Kevin J. Hopps" Any constructor starts with "raw bits" and transforms them into an object. An assignment operator works on an already existing object. Sometimes the copy constructor is written in terms of the assignment operator: Thing::Thing(Thing const& orig) { operator=(orig); } But if you do this you must remember that the members of Thing will be default-initialized. For objects, this means that the default constructor will be called. POD members will be garbage. So if your assignment operator depends upon valid values in the members, you may have a problem. This method can also be inefficient because the non-POD members are being set twice -- once to call the default constructor and then again to assign a new value to it. I try to write my copy constructors this way: Thing::Thing(Thing const& orig) : m_member1(orig.m_member1), m_member2(orig.m_member2), m_member3(orig.m_member3) // etc. { } This works for POD and non-POD members. If you have pointers that need to have their pointed-at contents copied, initialize them to NULL and implement the copy in the body of the constructor, but be careful to avoid memory leaks when exceptions occur. KOENIG: ark@research.att.com (Andrew Koenig) The assignment operator has two jobs: Get rid of whatever value the object previously had; Give it a new value. The copy constructor has one job: Give the object a new value. It therefore stands to reason that the assignment operator should call the copy constructor. Unfortunately, that's impossible, because you can't call constructors directly. Therefore, if you want to share code between the assignment operator and the copy constructor, you have to factor that code into a third function called, say, initialize(). Then the copy constructor will just call initialize(), and the assignment operator will get rid of the old value and then call initialize(). A little further thought should convince you that getting rid of the old value pretty much duplicates the destructor, so that code should be factored too. So you wind up with code that looks like this: Thing::initialize(Thing const& orig) { // some code goes here } Thing::destroy() { // some more code goes here } Thing::Thing(Thing const& orig) { initialize(orig); } Thing::~Thing() { destroy(); } Thing& operator=(Thing const& orig) { if (this != &orig) { destroy(); initialize(orig); } return *this; } Judicious use of inline functions can remove all or most of the overhead from this factorization. This technique is not always right, but it's often a good starting point.