Copy Construction and Assignment Stephen P Levitt School of Electrical and Information Engineering University of the Witwatersrand 2019
Copy Construction and Assignment
Stephen P Levitt
School of Electrical and Information EngineeringUniversity of the Witwatersrand
2019
Outline
1 Copying Objects — The Copy Constructor
2 Assigning Objects — The Assignment Operator
3 Copy Construction and Assignment Options
4 Derived Class Copy Construction and Assignment
Copy Construction and Assignment 1 / 19
Copy Construction
Copy construction creates a new object which is a duplicate of an existing object.
Account::Account(const Account& original)
Examples of when the copy constructor is called:
auto myAccount = Account{}; // calls the default constructor
auto anotherAccount = Account{myAccount}; // copy created on the stack
auto acc_ptr = make_unique<Account>(myAccount); // copy created on heap
void getAccountStatus(Account account) // pass-by-value copy created
Copy Construction and Assignment : Copying Objects — The Copy Constructor 2 / 19
The Compiler-Generated Copy Constructor
For the compiler-generated copy constructoreach data member of the class is copied using its own copy constructorprimitive types are simply copied
This is termed a memberwise copy.
Copy Construction and Assignment : Copying Objects — The Copy Constructor 3 / 19
Issues With the Compiler-Generated Copy Constructor
Sketch a memory map which illustrates the memory layout after the code in main hasbeen executed.
// in mainAddressBookEntry dana{"Dana","Dana.jpg"};AddressBookEntry tom{dana};// ----------------------------------------
class AddressBookEntry {public:AddressBookEntry(const string& name, const string& image_filename);// using compiler-generated copy constructor
private:string name_; // person's nameImage* image_ptr_; // image pointer
}
Copy Construction and Assignment : Copying Objects — The Copy Constructor 4 / 19
Assignment
Assignment sets an existing object equal to another existing object
Account yourAccount;
// calls the assignment operatoryourAccount = myAccount;
For the compiler-generated assignment operator:each data member is assigned in turn, using its own assignment operatorknown as memberwise assignment
Copy Construction and Assignment : Assigning Objects — The Assignment Operator 5 / 19
Consequences of Using the Compiler-Provided Copy Constructor andAssignment Operator
The compiler-generated copy constructor and assignment operator exhibit defaultmemberwise semantics and a shallow copy/assignment is made:
each data member of the class is copied in turn using its own copy constructor orassignment operatorstate will be shared if your class contains pointer data members
Typically, you want an independent copy.
Copy Construction and Assignment : Assigning Objects — The Assignment Operator 6 / 19
Assignment Issues — A Problematic Assignment Operatortom = dana;Does this work correctly? Assume the copy constructor for Image has been writtencorrectly.
2 void AddressBookEntry::operator=(const AddressBookEntry& rhs)3 {4 name_ = rhs.name_;5
6 delete image_ptr_;7 if (rhs.image_ptr_ != nullptr)8 // point to new image copy9 image_ptr_ = new Image{*(rhs.image_ptr_)};
10 else11 // point to null12 image_ptr_ = nullptr;13 }
Copy Construction and Assignment : Assigning Objects — The Assignment Operator 7 / 19
Problematic Assignment Operator: Clue — Withdrawing Cash from anATM; What Could Go Wrong?
Copy Construction and Assignment : Assigning Objects — The Assignment Operator 8 / 19
A Better (Atomic) Assignment Operator
1 void AddressBookEntry::operator=(const AddressBookEntry& rhs)2 {3 // use copy constructor to create temporary, assumes copy constructor4 // is written correctly5 AddressBookEntry temp{rhs};6
7 // swap temporary's data members with this object's8 name_.swap(temp.name_);9
10 // swap pointers11 Image* lhs_image_ptr = image_ptr_;12 image_ptr_ = temp.image_ptr_;13 temp.image_ptr_ = lhs_image_ptr;14
15 return;16 }
Copy Construction and Assignment : Assigning Objects — The Assignment Operator 9 / 19
Assignment Must be an Atomic Operation
Assignment must be atomic — it either happens completely or it does not happenat allAssignment can fail when constructing the temporary — then no assignmenttakes placeSwapping elements must be a no-fail operationAtomicity is a key concept for database transactions
Copy Construction and Assignment : Assigning Objects — The Assignment Operator 10 / 19
Returning the Left-Hand Operand
AddressBookEntry& AddressBookEntry::operator=(const AddressBookEntry& rhs)
{// use copy ctor to create temporaryAddressBookEntry temp{rhs};
// swap temporary's data members with this object'sname_.swap(temp.name_);
// swap pointersImage* lhs_image_ptr = image_ptr_;image_ptr_ = temp.image_ptr_;temp.image_ptr_ = lhs_image_ptr;
// return the lhs (good style)return *this;
}Copy Construction and Assignment : Assigning Objects — The Assignment Operator 11 / 19
Swapping data members
AddressBookEntry& AddressBookEntry::operator=(const AddressBookEntry& rhs)
{// use copy ctor to create temporaryAddressBookEntry temp{rhs};
// swap temporary's data members with this object'sname_.swap(temp.name_);
// swap pointersImage* lhs_image_ptr = image_ptr_;image_ptr_ = temp.image_ptr_;temp.image_ptr_ = lhs_image_ptr;
// return the lhs (good style)return *this;
}Copy Construction and Assignment : Assigning Objects — The Assignment Operator 12 / 19
Using a swap function
AddressBookEntry& AddressBookEntry::operator=(const AddressBookEntry& rhs)
{// use copy ctor to create temporaryAddressBookEntry temp{rhs};
// swap temporary with this object// must provide a no-fail (no throw) guaranteeswap(temp);
// return the lhs (good style)return *this;
}
Copy Construction and Assignment : Assigning Objects — The Assignment Operator 13 / 19
The Canonical Form of the Assignment Operator
Class& Class::operator=(const Class& rhs){
// use copy constructor to create a temporaryClass temp{rhs};
// swap temporary with this object// must provide a no-fail (no throw) guaranteeswap(temp);
// return the lhsreturn *this;
}
Copy Construction and Assignment : Assigning Objects — The Assignment Operator 14 / 19
Copy Constructor and Assignment Operator Options
Choose the appropriate option with regard to these functions:1 Let the compiler generate them automatically — make this explicit by using the
default keyword:Account(const Account& rhs) = default;Account& operator=(const Account& rhs) = default;
2 Write your own versions, taking full responsibility for construction and assignment3 Disallow copy construction and assignment:
Account(const Account& rhs) = delete;Account& operator=(const Account& rhs) = delete;
Copy Construction and Assignment : Copy Construction and Assignment Options 15 / 19
Derived Class Copy Construction and Assignment
Each class in the hierarchy should be responsible for its own data membersDerived classes should rely on their base classes to correctly copy construct orassign base class membersIn the absence of programmer-provided copy constructors/assignment operatorsthe compiler will revert to default memberwise initialisation or assignmentIf you provide your own copy constructor or assignment operator in a derived classyou are then responsible for copying/assigning all data members including those inthe base class by reusing base class functionality (DRY)
Copy Construction and Assignment : Derived Class Copy Construction and Assignment 16 / 19
Derived Class Copy Constructor Example
// A copy constructor is not actually required for ColourRect
ColourRect(const ColourRect& rhs):
// calls Rectangle's copy cstor, copies the Rectangle part ofColourRect
Rectangle{rhs},
// copies ColourRect data memberscolour_{rhs.colour_}
{}
Copy Construction and Assignment : Derived Class Copy Construction and Assignment 17 / 19
Derived Class Assignment Operator ExampleFollow the canonical form:
// An assignment op is not actually required for ColourRect
ColourRect& operator=(const ColourRect& rhs){
// use copy cstor to create temporaryColourRect temp{rhs};
// swap temporary with this object must provide a no-fail guaranteeswap(temp);
// return the lhsreturn *this;
}
Copy Construction and Assignment : Derived Class Copy Construction and Assignment 18 / 19
Derived Class Assignment Operator Example cont.
void ColourRect::swap(ColourRect& other){
// call Rectangle's swap to swap Rectangle's data membersRectangle::swap(other);
// swap ColourRect's data membersstd::swap(colour_, other.colour_);
}
Copy Construction and Assignment : Derived Class Copy Construction and Assignment 19 / 19