Introduction to move semantics (part 2)

This lesson contains approximately 25 minutes of video content.

Transferring ownership explicitly with std::move()

In this video, I write zero in a vector's size field in the memory diagram examples, but for some reason say one both times. I meant to say zero, just like I wrote it!

Move semantics for our doubly linked list

Summary and additional considerations

Activity: Move semantics for our naive unique pointer implementation

Graded Playground Autograder

Activity Prompt:

Unique pointer

The mantra of the unique pointer is exclusive ownership and accordingly implements a move-only type. The unique pointer implementation utilizes the resource acquisition is initialization (RAII) programming idiom, where the lifetime of a dynamically allocated object (i.e., the resource) is tied to the unique pointer object that owns it.

The allocation of the dynamically allocated object (i.e., resource acquisition) owned by the unique pointer happens during construction (initialization). Deallocation of that object is always completed during destruction. A non-null By its name, the unique pointer always owns what it points to. Therefore, two objects of this type will never share the same resource. This invariant is maintained by disabling the copy mechanisms for this type.

In this activity

You will implement move semantics for UniquePtr.

Member functions you are to implement
UniquePtr(UniquePtr<T>&& rhs); Move constructor. Transfers ownership of rhs.holder_ to this object (i.e., that on left-hand side of =).
UniquePtr<T>& operator=(UniquePtr<T>&& rhs); Move assignment operator. Transfers ownership of rhs.holder_ to this object (i.e., that on left-hand side of =). Ensures no memory is leaked.
Provided member functions
UniquePtr(); We will use the default, compiler-generated definition of the default constructor.
UniquePtr(const T& data); Allocates a new dynamically allocated object of type T on the free store that is initialized with a copy of data.
UniquePtr(const UniquePtr<T>& rhs); deleted.
UniquePtr<T>& operator=(const UniquePtr<T>& rhs); deleted.
~UniquePtr(); Deallocates the dynamically allocated object pointed to by holder_.
Data members
T* holder_; holder_ points to the dynamically allocated object owned by UniquePtr.
#include <iostream> #include "unique-ptr.hpp" int main() { // // Move constructor call // UniquePtr<int> rhs_1(11); // UniquePtr<int> lhs_1(std::move(rhs_1)); // // Move assignment operator call // UniquePtr<int> rhs_2(7); // UniquePtr<int> lhs_2(11); // lhs_2 = std::move(rhs_2); }
#ifndef UNIQUE_PTR_HPP #define UNIQUE_PTR_HPP template <typename T> class UniquePtr { public: UniquePtr() = default; UniquePtr(const T& data); UniquePtr(const UniquePtr<T>& rhs) = delete; UniquePtr<T>& operator=(const UniquePtr<T>& rhs) = delete; ~UniquePtr(); // Functions to implement: // UniquePtr(UniquePtr<T>&& rhs); // UniquePtr<T>& operator=(UniquePtr<T>&& rhs); private: T* holder_ = nullptr; }; template <typename T> UniquePtr<T>::UniquePtr(const T& data) { holder_ = new T(data); } template <typename T> UniquePtr<T>::~UniquePtr() { delete holder_; } #endif
#include "unique-ptr.hpp"