Presentation is loading. Please wait.

Presentation is loading. Please wait.

CSE 332: C++ copy control I Copy Control (Part I) Copy control consists of 5 distinct operations –A copy constructor initializes an object by duplicating.

Similar presentations


Presentation on theme: "CSE 332: C++ copy control I Copy Control (Part I) Copy control consists of 5 distinct operations –A copy constructor initializes an object by duplicating."— Presentation transcript:

1 CSE 332: C++ copy control I Copy Control (Part I) Copy control consists of 5 distinct operations –A copy constructor initializes an object by duplicating the const l-value that was passed to it by reference –A copy-assignment operator (re)sets an object’s value by duplicating the const l-value passed to it by reference –A destructor manages the destruction of an object –A move constructor initializes an object by transferring the implementation from the r-value reference passed to it –A move-assignment operator (re)sets an object’s value by transferring the implementation from the r-value reference passed to it Today we’ll focus on the first 3 operations and will defer the others (introduced in C++11) until next time –The others depend on the new C++11 move semantics

2 CSE 332: C++ copy control I Basic Copy Control Operations A copy constructor or copy-assignment operator takes a reference to a (usually const) instance of the class –Copy constructor initializes a new object from it –Copy-assignment operator sets object’s value from it –In either case, original the object is left unchanged (which differs from the move versions of these operations) –Destructor takes no arguments (except implicit this ) Copy control operations for built-in types –Copy construction and copy-assignment copy values –Destructor of built-in types does nothing (is a “no-op”) Compiler-synthesized copy control operations –Just call that same operation on each member of the object –Uses defined/synthesized definition of that operation for user-defined types (see above for built-in types)

3 CSE 332: C++ copy control I Preventing or Allowing Basic Copy Control Old (C++03) way to prevent compiler from generating a default constructor, copy constructor, destructor, or assignment operator was somewhat awkward –Declare private, don’t define, don’t use within class –This works, but gives cryptic linker error if operation is used New (C++11) way to prevent calls to any method –End the declaration with = delete (and don’t define) –Compiler will then give an intelligible error if a call is made C++11 allows a constructor to call peer constructors –Allows re-use of implementation (through delegation) –Object is fully constructed once any constructor finishes C++11 lets you ask compiler to synthesize operations –Explicitly, but only for basic copy control, default constructor –End the declaration with = default (and don’t define)

4 CSE 332: C++ copy control I Shallow Copy Construction There are two ways to “copy” –Shallow: re-aliases existing resources E.g., by copying the address value from a pointer member variable –Deep: makes a complete and separate copy I.e., by following pointers and deep copying what they alias Version above shows shallow copy –Efficient but may be risky (why?) –Usually want no-op destructor, aliasing via shared_ptr // just uses the array that’s already in the other object IntArray::IntArray(const IntArray &a) :size_(a.size_), values_(a.values_) { }

5 CSE 332: C++ copy control I Deep Copy Construction This code shows deep copy –Safe: no shared aliasing, exception aware initialization –But may not be as efficient as shallow copy in many cases Note trade-offs with arrays –Allocate memory once –More efficient than multiple calls to new (heap search) –Constructor and assignment called on each array element –Less efficient than block copy E.g., using memcpy() –But sometimes necessary i.e., constructors, destructors establish needed invariants // makes its own copy of the array IntArray::IntArray(const IntArray &a) :size_(0), values_(nullptr) { if (a.size_ > 0) { // new may throw bad_alloc, // set size_ after it succeeds values_ = new int[a.size_]; size_ = a.size_; // could use memcpy instead for (size_t i = 0; i < size_; ++i) { values_[i] = a.values_[i]; }

6 CSE 332: C++ copy control I Swap Trick for Copy-Assignment Cleanup/assignment succeed or fail together class Array { public: Array(unsigned int) ; // assume constructor allocates memory Array(const Array &); // assume copy constructor makes a deep copy ~Array(); // assume destructor calls delete on values_ Array & operator=(const Array &a); private: size_t size_; int * values_; }; Array & Array::operator=(const Array &a) { // return ref lets us chain if (&a != this) { // note test for self-assignment (safe, efficient) Array temp(a); // copy constructor makes deep copy of a swap(temp.size_, size_); // note unqualified calls to swap swap(temp.values_, values_); // (do user-defined or std::swap) } return *this; // previous *values_ cleaned up by temp’s destructor }

7 CSE 332: C++ copy control I Constructors and Destructors are Inverses Constructors initialize –At the start of each object’s lifetime –implicitly called when object is created Destructors clean up –Implicitly called when an object is destroyed E.g., when stack frame where it was declared goes out of scope E.g., when its address is passed to delete E.g., when another object of which it is a member is being destroyed IntArray::IntArray(unsigned int u) : size_(0), values_(nullptr) { // exception safe semantics values_ = new int [u]; size_ = u; } IntArray::~IntArray() { // deallocates heap memory // that values_ points to, // so it’s not leaked: // with deep copy, object // owns the memory delete [] values_; // the size_ and values_ // member variables are // themselves destroyed // after destructor body }

8 CSE 332: C++ copy control I More on Initialization and Destruction Initialization follows a well defined order –Base class constructor is called That constructor recursively follows this order, too –Member constructors are called In order members were declared Good style to list in that order (a good compiler may warn if not) –Constructor body is run Destruction occurs in the reverse order –Destructor body is run, then member destructors, then base class destructor (which recursively follows reverse order) Make destructor virtual if members are virtual –Or if class is part of an inheritance hierarchy –Avoids “slicing”: ensures destruction starts at the most derived class destructor (not at some higher base class)


Download ppt "CSE 332: C++ copy control I Copy Control (Part I) Copy control consists of 5 distinct operations –A copy constructor initializes an object by duplicating."

Similar presentations


Ads by Google