New version page

Stanford CS 107 - Copy Constructor and operator

Upgrade to remove ads
Upgrade to remove ads
Unformatted text preview:

CS107L Handout 02Autumn 2007 October 5, 2007Copy Constructor and operator=Much of the surrounding prose written by Andy Maag, CS193D instructor from years ago.The compiler will supply a default (zero-argument) constructor if the programmerdoesn’t. This default constructor will call each data member’s default constructor inorder to fully initialize the object. If the programmer wishes to displace the defaultconstructor, he simply provides one. The same thing goes for the destructor.There is another type of compiler-synthesized constructor—the copy constructor, andit's called whenever an object needs to be constructed from an existing one.Suppose we had a class to encapsulate strings, and we call this class string. The detailsof the dynamic memory management are annoying enough that we might want toabstract those details away.// string.h, take oneclass string {public:string(const char *str = "");~string();private:initializeFrom(const char *front, const char *end)char *front;char *end;};// string.cc take onestring::string(const char *str){initializeFrom(str, str + strlen(str));}string::~string(){delete[] front;}void string::initializeFrom(const char *front, const char *end){int length = end - front;this->front = new char[length + 1];this->end = this->front + length;strncpy(this->front, front, length + 1); // include the '\0'}2For this example, we’ll assume that the string constructor allocates space for thecharacters, and the destructor frees up that same space. Internally, the are two iterator-like points that point to the leading character and the null character at the end. TheThe copy constructor may be called when doing simple initializations of a string object:string professor("Professor Plum");string clone = professor; // copy constructor gets called.More importantly, the copy constructor is called when passing an object by value, orreturning an object by value. For instance, we might have a function that translates asentence to Pig Latin:static string translate(string sentence){// tokenizes, rotates, and rebuilds translation}We might declare a string and call the translate function like this:string excuse("I need an extension because I forgot I was in CS107L.");cout << "Translation: \"" << translate(excuse) << "\"" << endl;When passing the sentence object, the copy constructor is called to copy the stringobject from the calling function to the local parameter in the translate function.Because we did not specify a copy constructor, the default copy constructor is called. Inthis case, it’s just not what we want.Default Copy ConstructorThe default copy constructor does a member-wise copy of all the primitive andembedded object fields. For our string class, the default copy constructor simplycopies the two pointers that are embedded inside, as it would for any set of pureprimitive types. However, the characters themselves are not copied. This is called ashallow copy, because it only copies the data down to one level. In memory, what we’dhave would look like this:excusesentenceIneedL.\03This causes a problem because now the two objects share the same characters data. Ifwe changed any of the characters within the sentence object, it would change thecharacters in the excuse as well. What’s worse is that after the translate functionexits, the string destructor is called on the sentence object, which frees the characterarray more officially owned by excuse. Bad times.What We Want: The Deep CopyIn order to avoid potential disasters like this, what we want is a deep copy of the stringobject. That means we want the copy constructor to synthesize of new character arraythat’s a logical clone of the original, but memory independent of it.What we want is a picture in memory which looks like this:Now we can manipulate the characters within the sentence object and not affect theoriginal excuse object. When the character array within the copy is freed on exit thetranslate function, the original string object is still going strong. The copyconstructor (be it the bad compiler-provided one or the correct user-defined one) is alsoinvoked when returning an object by value. We didn’t even begin to hit on thoseproblems, though they are effectively the same.Declaring a Copy ConstructorIn order to provide deep-copy semantics for our string object, we need to declare ourown copy constructor. A copy constructor takes a constant reference to an object of theclass’ type as a parameter and has no return type. We would declare the copyconstructor for the string within the class declaration like this:// string.h take twoclass string {public:string(const char *str = "");string(const string& original);~string();private:void initializeFrom(const char *front, const char *end);char *front;char *end;};excusesentenceIneedL.\0IneedL.\04We’d implement the copy constructor like this:string::string(const string& original){initializeFrom(original.front, original.end);}You should provide a copy constructor for any class for which you want deep copysemantics and the compiler will do the wrong thing. If the class only has data membersthat are integral types (that is, it contains no pointers or open files) and/or direct objects(which have properly implemented copy constructors), you can omit the copyconstructor and let the default copy constructor handle it.LimitationsThe copy constructor is not called when doing an object-to-object assignment. Forinstance, if we had the following code, we would still only get a shallow copy:string betty("Betty Rubble"); // Initializes string to "Betty Rubble"string wilma; // Initializes string to empty stringwilma = betty;This is because the assignment operator is being called instead of the copy constructor.By default, the assignment operator does a member-wise copy of the object, which inthis case gives a shallow copy. However, C++ gives us the ability to override the defaultassignment operator, and we’ll learn that today too.Incidentally, there may be cases when you want to prevent anyone from copying a classobject via the copy constructor. By declaring a copy constructor as a privateconstructor within the class definition and not implementing it, the compiler will preventthe passing of objects of that class by value.AssignmentIt is possible to redefine the assignment operator for a class. The assignment operatormust be defined as a member function in order to guarantee that the left-hand operandis an object. By default, the


View Full Document
Download Copy Constructor and operator
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Copy Constructor and operator and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Copy Constructor and operator 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?