1 CSCI 104 Copy Semantics Mark Redekopp David Kempe
2 Copy constructors and assignment operators COPY SEMANTICS
3 Get the Code • On your VM run the command: – wget http://ee.usc.edu/~redekopp/cs104/copycon.cpp
4 this Pointer • How do member functions know which 0x7e0 object’s data to be operating on? cards[52] 37 21 4 9 16 43 20 39 d2 • d1 is implicitly passed via a special pointer top_index 0 call the ‘ this ’ pointer 0x2a0 #include<iostream> #include “ deck.h ” cards[52] poker.cpp 41 27 8 39 25 4 11 17 d1 int main(int argc, char *argv[]) { passed to shuffle() top_index 1 Deck d1, d2; d1 is implicitly d1.shuffle(); this int main() { Deck d1; d1.shuffle(); #include<iostream> 0x2a0 } #include “ deck.h ” void Deck::shuffle(Deck *this) { void Deck::shuffle() d1.shuffle(); this->cut(); // calls cut() { ... // for this object cut(); // calls cut() } for(i=0; i < 52; i++){ // for this object for(i=0; i < 52; i++){ int r = rand() % (52-i); deck.cpp int temp = this->cards[r]; int r = rand() % (52-i); deck.cpp this->cards[r] = this->cards[i]; int temp = cards[r]; this->cards[i] = temp; cards[r] = cards[i]; } cards[i] = temp; } } } Actual code you write Compiler-generated code
5 Another Use of 'this' class Student { • This can be used public: Student(string name, int id, double gpa); to resolve ~Student(); // Destructor private: string name; scoping issues int id; double gpa; with similar }; named variables Student::Student(string name, int id, double gpa) { // which is the member and which is the arg? name = name; id = id; gpa = gpa; } Student::Student(string name, int id, double gpa) { // Now it's clear this ->name = name; this ->id = id; this ->gpa = gpa; }
6 Struct/Class Assignment • Assigning one struct or class object to another will perform an element by element copy of the source struct/class to the destination struct/class #include<iostream> using namespace std; ‘B’ 0x00 enum {CS, CECS }; ‘ i ’ 0x01 struct student { name … … char name[80]; s1 0x4F 00 int id; int major; 0x50 5 id }; 0x54 1 major ‘B’ int main(int argc, char *argv[]) … { ‘ i ’ student s1,s2; name … strncpy (s1.name,”Bill”,80); s2 … 00 … s1.id = 5; s1.major = CS; s2 = s1; 5 id return 0; 1 major } Memory
7 Multiple Constructors • Can have multiple class Student { public: Student(); // Constructor 1 constructors with Student(string name, int id, double gpa); // Constructor 2 Sutdent.h different argument lists ~Student(); // Destructor string get_name(); int get_id(); double get_gpa(); void set_name(string name); void set_id(int id); void set_gpa(double gpa); #include<iostream> private: #include “ student.h ” string _name; int _id; int main() double _gpa; { }; Student s1; // calls Constructor 1 string myname; Student::Student() cin >> myname; { s1.set_name(myname); _name = “”, _id = 0; _ gpa = 2.0; Student.cpp s1.set_id(214952); } s1.set_gpa(3.67); Student::Student(string name, int id, double Student s2(myname, 32421, 4.0); gpa) // calls Constructor 2 { _name = name; _id = id; _gpa = gpa; } }
8 Copy Constructors • class Complex Write a prototype for the constructor that { would want to be called by the red line of public: Complex(int r, int i); code // What constructor definition do I • Realm of Reasonable Answers: // need for c3's declaration below – Complex(Complex) ~Complex() • We will see that this can't be right… private: int real, imag; – Complex(Complex &) }; – Complex(const Complex &) int main() { • We want a constructor that will build a Complex c1(2,3), c2(4,5) new Complex object (c3) by making a Complex c3(c1); copy of another (c1) }
9 Assignment & Copy Constructors • class Complex C++ compiler automatically generates a { default copy constructor public: Complex(int r, int i); – Constructor called when an object is allocated // compiler will provide by default: // Complex(const Complex& ); and initializes the object to be a copy of // Complex& operator=(const Complex&); another object of the same type ~Complex() – Signature would look like private: int real, imag; Complex(const Complex &); Class Complex }; – Called by either of the options shown in the int real_ code int main() int imag_ { – Simply performs an element by element copy Complex c1(2,3), c2(4,5) • C++ compiler automatically generates a Complex c3(c1); // copy constructor Complex c4 = c1; // copy constructor default assignment function c4 = c2; // default assignment oper. – Called when you assign to an object that is // c4.operator=(c2) already allocated (memory already exists) } – c4 c2 Simply performs an element by element copy – Complex& operator=(const Complex &); int real_ int real_ int imag_ int imag_
10 Assignment & Copy Constructors • class MyArray C++ compiler automatically generates a { default copy constructor public: MyArray(int d[], int num); //normal • C++ compiler automatically generates a ~MyArray(); int len; int *dat; default assignment function }; • See picture below of what a1 looks like as // Normal constructor MyArray::MyArray(int d[], int num) it is constructed { dat = new int[num]; len = num; for(int i=0; i < len; i++){ dat[i] = d[i]; } } int main() { vals 0 1 2 3 int vals[] = {9,3,7,5}; MyArray a1(vals,4); 9 3 7 5 MyArray a2(a1); // calls default copy MyArray a3 = a1; // calls default copy a1.dat 0x200 a1.len 4 MyArray a4; a4 = a1; // calls default assignment 0x200 0 1 2 3 0x200 0 1 2 3 // how are the contents of a2, a3, a4 // related to a1 9 3 7 5 } After 'new' After constructor
11 Assignment & Copy Constructors vals 0 1 2 3 class MyArray { 9 3 7 5 public: MyArray(int d[], int num); //normal ~MyArray(); A1 a1.len 4 int len; int *dat; 0x200 a1.dat 0x200 }; 0 1 2 3 // Normal constructor MyArray::MyArray(int d[], int num) 9 3 7 5 { After constructor dat = new int[num]; len = num; A2 a2.len 4 for(int i=0; i < len; i++){ a2.dat 0x200 dat[i] = d[i]; } } A3 a3.len 4 int main() a3.dat 0x200 { int vals[] = {9,3,7,5}; Default copy constructor A4 a4.len 4 MyArray a1(vals,4); and assignment operator MyArray a2(a1); // calls default copy a41.dat 0x200 make a SHALLOW COPY MyArray a3 = a1; // calls default copy MyArray a4; (data members only) a4 = a1; // calls default assignment rather than a DEEP copy // how are the contents of a2, a3, a4 (data members + what // related to a1 } they point at)
12 When to Write Copy Constructor • Default copy constructor and assignment operator ONLY perform SHALLOW copies – SHALLOW COPY (data members only) – DEEP copy (data members + what they point at) – [Like saving a webpage to your HD…it makes a shallow copy and doesn't copy the pages linked to] • You SHOULD/MUST define your own copy constructor and assignment operator when a DEEP copy is needed – When you have pointer data members that point to data that should be copied when a new object is made – Often times if your data members are pointing to dynamically allocated data, you need a DEEP copy • If a Shallow copy is acceptable, you do NOT need to define a copy constructor
13 Defining Copy Constructors class MyArray {public: • Same name as normal MyArray(int d[], int num); constructor but should MyArray(const MyArray& rhs); ~MyArray(); take in an argument of private: int *dat; int len; the object type: } – // Normal constructor Usually a const reference MyArray::MyArray(int d[], int num) • MyArray(const MyArray&); { dat = new int[num]; len = num; // copy values from d to dat } // Copy constructor MyArray::MyArray(const MyArray &rhs){ { len = rhs.len; dat = new int[len]; // copy from rhs.dat to dat } int main() { intvals[] = {9,3,7,5}; MyArray a1(vals,4); MyArray a2(a1); MyArray a3 = a1; // how are the contents of a2 and a1 related? }
14 Implicit Calls to Copy Constructor • class Complex Recall pass-by-value { passes a copy of an public: Complex(intr, inti); object…If defined the Complex Complex(const Complex &rhs); ~Complex(); copy constructor will int real, imag; automatically be called }; // Copy constructor to make this copy Complex::Complex(const Complex &c) { otherwise the default cout << "In copy constructor" << endl; copy will perform a real = c.real; imag = c.imag; } shallow copy // ** Copy constructor called for pass-by-value int dummy(Complex rhs) { cout << "In dummy" << endl; } intmain() { Complex c1(2,3), c2(4,5); int x = dummy(c1); // ** Copy Constructor called on c1 ** }
Recommend
More recommend