1 / 7

Copy Control (Part II)

Copy Control (Part II). Review: 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

clara
Download Presentation

Copy Control (Part II)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Copy Control (Part II) • Review: 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 last 2 operations and other features (introduced in C++11) like r-value references • I.e., features that support the new C++11 move semantics

  2. Motivation for Move Semantics • Copy construction and copy-assignment may be expensive due to time/memory for copying • It would be more efficient to simply “take” the implementation from the passed object, it that’s ok • It’s ok if the passed object won’t be used afterward • E.g., if it was passed by value and so is a temporary object • E.g., if a special r-value reference says it’s ok to take from (as long as object remains in a state that’s safe to destruct) • Note that some objects require move semantics • I.e., types that don’t allow copy construction/assignment • E.g., unique_ptr, ifstream, thread, etc. • New for C++11: r-value references and move function • E.g., int i; int &&rvri = std::move(i);

  3. Synthesized Move Operations • Compiler will only synthesize a move operation if • Class does not declare any copy control operations, and • Every non-static data member of the class can be moved • Members of built-in types can be moved • E.g., by std::move etc. • User-defined types that have synthesized/defined version of the specific move operation can be moved • L-values are always copied, r-values can be moved • If there is no move constructor, r-values only can be copied • Can ask for a move operation to be synthesized • I.e., by using = default • But if cannot move all members, synthesized as = delete

  4. R-Values, L-Values, and References to Either • A variable is an l-value (has a location) • E.g., int i = 7; • Can take a regular (l-value) reference to it • E.g., int & lvri = i; • An expression is an r-value • E.g., i * 42 • Can only take an r-value reference to it (note syntax) • E.g., int && rvriexp = i * 42; • Can only get r-value reference to l-value via move • E.g., int && rvri = std::move(i); • Promises that i won’t be used for anything afterward • Also, must be safe to destroy i (could be stack/heap/global)

  5. Note r-value reference Says it’s safe to take a’s implementation from it Promises only subsequent operation will be destruction Note constructor design A lot like shallow copy constructor’s implementation Except, zeroes out state of a No sharing, current object owns the implementation Object a is now safe to destroy (but is not safe to do anything else with afterward) // takes implementation from a IntArray::IntArray(IntArray &&a) : size_(a.size_), values_(a.values_) { // make a safe to destroy a.values_ = nullptr; a.size_ = 0; } Move Constructors

  6. Move-Assignment Operators • No allocation, so no exceptions to worry about • Simply free existing implementation (delete values_) • Then copy over size and pointer values from a • Then zero out size and pointer in a • This leaves assignment complete, a safe to destroy • Implementation is transferred from a to current object Array & Array::operator=(Array &&a) { // Note r-value reference if (&a != this) { // still test for self-assignment delete [] values_; // safe to free first (if not self-assigning) size_ = a. size_; // take a’s size value values_ = a.values_; // take a’s pointer value a.size_ = 0; // zero out a’s size a.values_ = nullptr; // zero out a’s pointer (now safe to destroy) } return *this; }

  7. Move Semantics and Inheritance • Base classes should declare/define move operations • If it makes sense to do so at all • Derived classes then can focus on moving their members • E.g., calling Base::operator= from Derived:: version • Containers further complicate these issues • Containers hold their elements by value • Risks slicing, other inheritance and copy control problems • So, put (smart) pointers, not objects, into containers • Access is polymorphic if destructors, other methods virtual • Smart pointers may help reduce need for copy control operations, or at least simplify cases where needed

More Related