Contents Destructor The Big Three The Big Three Copy constructor Copy constructor Assignment operator Move constructor (C++11) Move assignment operator (C++11) Move assignment operator (C++11) C++ Object Oriented Programming C Obj O i d P i The managed pointer Pei-yih Ting NTOUCS 20-1 20-2 Introduction Copy Constructor (copy ctor) py ( py ) When the class has the functionality of resource management , it is very likely What is a copy constructor? X(X&) that the destructor (dtor), the copy constructor (copy ctor), and the assignment Account(Account &src); and Account(const Account &src); Account(Account &src); and Account(const Account &src); operator occur together. h called the BIG 3 Resource management: ex. When is the copy constructor invoked? object being copied class Account { Case 1 :Account customer1("Sean Pan", C 1 A t t 1("S P " public: i Account(const char *name, const char *phone, const char *address); "123-4567890", "1234 Sunset Blvd."); ~Account(); …. Account customer2(customer1); Account customer2(customer1); private: Account customer3 = customer1; char *m_name; char *m_phone; remote ownership Case 2 : void fun1(Account customer) { ( ) { char *m address; _ ; }; … Account::Account(const char *name, const char *phone, const char *address) { } m_name = new char[strlen(name)+1]; strcpy(m_name, name); C Case 3 : Account fun2() { 3 A t f 2() { m_phone = new char[strlen(phone)+1]; strcpy(m_phone, phone); h h [ t l ( h )+1] t ( h h ) m_address = new char[strlen(address)+1]; strcpy(m_address, address); Account x; } … Account:: Account() { Account::~Account() { return x; dtor delete[] m_name; delete[] m_phone; delete[] m_address; } } 20-3 20-4
Copy Constructor py Dangling Reference g g If copy ctor is not defined, compiler will synthesize one for you. Consider the following codes This synthesized copy ctor copies all the bits of the object This synthesized copy ctor copies all the bits of the object. void main() { Account customer("Sean Pan", "123-4567890", "1234 sunset Blvd."); For many cases this implementation is good but for a class which … allocates memory or handles other resources itself this usually leads allocates memory or handles other resources itself, this usually leads fun(customer); f ( t ) … to errors. A trap to dangling reference . customer.display(); // show all the customer information customer 1 customer 2 } } shallow copy shallow copy m_name m_name void fun(Account customerLocal) { m_phone m_phone 12 bytes y …. m_address m_address } // the dtor would deallocate the memory belongs to customerLocal // however, these memory blocks are the same as those of customer The statement fun(customer) would cause dangling reference and "Sean Pan" the statement customer.display() would access memory blocks Is this really we want? Is this really we want? ? ? previously belonged to this customer object and display some previously belonged to this customer object and display some "123 4567890" "123-4567890" strange contents. "1234 Sunset Blvd." 20-5 20-6 Unexpected Release p Example Copy Constructor p py Account::Account(const Account &src) { Sometimes, the resource might be unexpectedly released, ex. m name = new char[strlen(src.m name)+1]; _ [ ( _ ) ]; void main() { void readFile(ifstream is) { strcpy(m_name, src.m_name); ifstream infile("input.dat"); … m_phone = new char[strlen(src.m_phone)+1]; } } strcpy(m_phone, src.m_phone); t ( h h ) … m_address = new char[strlen(src.m_address)+1]; readFile(infile); VC 2010 does not allow this strcpy(m_address, src.m_address); … … } } Copy ctor is a kind of ctor. You should use initialization list whenever possible. Especially, you should invoke the base class whenever possible Especially you should invoke the base class This is a complex problem. The program will have runtime error. copy ctor if it is a derived class. You should invoke the component Why does the error occurs? You won't be able to correct this by class copy ctor if it contains a member object. py j supplying a copy constructor for ifstream because it is a library class. In a copy ctor, you are initiating an object from another object. The only thing you can easily do is not invoking the copy ctor by The memory space for the object is allocated by the system. passing the parameter with reference . i th t ith f If you want to forbid public usage of call-by-value semantics of an object, you can declare a private copy ctor for that class. 20-7 20-8
Member Object and Base Class j Assignment Operator g p Copy constructor is a constructor, member objects and base class When/where is the assignment operator invoked? must be initialized through initialization list must be initialized through initialization list Account customer1("abc" "1234" "ABC street"); Account customer1( abc , 1234 , ABC street ); Account customer2, customer3; // assume default ctor defined For example: Compiler adds Base() invocation customer2 customer1; Note: Note: automatically automatically class Derived: public Base { class Derived: public Base { customer2.operator (customer1); public: Derived::Derived(const Derived &src) customer3 customer2 customer1; … : m_obj(src.m_obj) { Derived(const Derived &src); D i d( t D i d & ) Note: Account customer2 = customer1; N t A t t 2 t 1 … … does not invoke the assignment operator } private: What is its prototypes? What is its prototypes? Derived::Derived(const Derived &src) { Derived::Derived(const Derived &src) { Component m_obj; … Account & operator=(const Account & rhs); }; } Compiler adds Base(), m_obj() No extra copy ctor invoked Derived::Derived(const Derived &src) Designed for continuously assignment invocations automatically : Base(src), m_obj(src.m_obj) { customer3 operator (customer2 operator (customer1)); … customer3.operator (customer2.operator (customer1)); } You have to chain manually. Note: this does not contradict the rule that reference does not bind to temporary object Compiler supplied copy ctor also chains correctly. 20-9 20-10 Assignment Operator g p Assignment Operator g p Again, if the class being designed allocates its own resources . It is You can declare the assignment operator in the private section to quite often to see the dtor , copy ctor , and the assignment operato r q , py , g p forbid public usage of the assignment semantics. occur together. If there is a reference variable or a const variable defined in the class, There are seven important things to do in an assignment operator th there is no way to define the assignment operator. i t d fi th i t t Account &Account::operator (const Account &rhs) Detecting self assignments { if (&rhs == this) return *this; ( ) ; Usually the assignment operator repeats the codes both in the copy Usually, the assignment operator repeats the codes both in the copy delete[] m_name; delete[] m_phone; delete[] m_address; ctor and the dtor. It is common to prepare common functions to be m_name = new char[strlen(rhs.m_name)+1]; called in assignment operator, copy ctor and the dtor. g p , py m phone = new char[strlen(rhs m phone)+1]; m_phone new char[strlen(rhs.m_phone)+1]; m_address = new char[strlen(rhs.m_address)+1]; strcpy(m_name, rhs.m_name); The Big 3 are never inherited because based class functions are not strcpy(m phone rhs m phone); strcpy(m_phone, rhs.m_phone); sufficient to initialize, copy, or destroy a derived instance. strcpy(m_address, rhs.m_address); // invoke the base class assignment operator // invoke the component object assignment operator // i k h bj i Three make a team. Do not forget any one of them. return *this; } 20-11 20-12
Recommend
More recommend