5.2.10 · D1C++ Programming

Foundations — Move constructor and move assignment — Rule of Five

1,675 words8 min readBack to topic

This page assumes you have seen almost nothing. Before you can read a move constructor, you need to see what a pointer, the heap, an lvalue, and an rvalue actually are. We build each one from a picture, in the order they depend on each other.


1. Memory: the stack and the heap

Why the topic needs this: a move "steals a resource". The resource is almost always a block on the heap. If everything lived on the stack there would be nothing expensive to steal — the whole point of moving is to avoid re-copying a heap block.

Figure — Move constructor and move assignment — Rule of Five

Look at the figure: the small box data_ sits on the stack, but the arrow it draws points to a long strip on the heap. That arrow is the next concept.


2. A pointer: an arrow to a place in memory

  • new int[n] — ask the heap for room for n integers, get back the address of the first one.
  • delete[] p — hand that heap block back. Do this exactly once.
Figure — Move constructor and move assignment — Rule of Five

3. nullptr: an arrow pointing at nothing

Why the topic needs it: after a move steals the heap block, the source object still exists and its destructor will still run. If we leave the source's pointer aimed at the stolen block, its destructor frees our block → double free. Setting the source to nullptr makes its destructor a safe no-op: delete[] nullptr; is defined to do nothing.


4. size_t: a plain "count of things"

We need it because a heap block does not remember its own length; the owning object must store it alongside the pointer.


5. Constructor & destructor: birth and death of an object

Picture: birth = draw the box and its arrow to a fresh heap strip. Death = the box is erased, and the destructor must first erase the heap strip it pointed to (delete[]), otherwise that strip leaks forever.

Why the topic needs it: the Rule of Five is a rule about these functions. Every one of the five is either the constructor family or the destructor.


6. class and members: bundling the handle with its length

class Buffer {
    int*   data_;   // the arrow (pointer)
    size_t size_;   // the length tag
public:
    // ... the five special members go here
};

This is the object we will learn to move. Everything above was to let you read those two member lines with full understanding.


7. lvalue vs rvalue: does it have a lasting name?

This is the concept that decides when a move is allowed.

Figure — Move constructor and move assignment — Rule of Five

8. noexcept: a promise not to throw

Why the topic needs it: std::vector will only move your objects during a reallocation if the move is noexcept; otherwise it silently falls back to copying to preserve safety. Detail lives in Exception safety guarantees.


How these feed the topic

Stack vs Heap

Pointer = arrow to heap

nullptr = arrow to nothing

Double free danger

size_t length tag

class Buffer bundles pointer + length

Constructor and Destructor

Move steal then null source

lvalue vs rvalue

rvalue reference T and and

noexcept promise

Rule of Five


Where to go next

  • Parent: the full Rule of Five topic
  • Rule of Three — the pre-move ancestor (destructor + two copy members)
  • Rule of Zero — let RAII members own resources so you write none of the five
  • std::move and rvalue references — the cast that turns an lvalue into a movable rvalue
  • Copy elision and RVO — when even the move is skipped entirely
  • Smart pointers (unique_ptr / shared_ptr) — pre-built move-only owners
  • Exception safety guarantees — why noexcept matters for container moves

Equipment checklist

Where does memory you request with new live, and who frees it?
On the heap; you free it by hand with delete[] (or a RAII wrapper does it for you).
What does a pointer actually store?
An address — the location of some other data; drawn as an arrow to another box.
Why is copying a pointer cheap but copying its target expensive?
The pointer is ~8 bytes; the heap block it points to can be thousands of bytes.
What does nullptr mean and why null a moved-from source?
It is a pointer to nothing; nulling the source makes its destructor a safe no-op so it won't free the block we stole.
What disaster happens if two pointers hold the same address and both delete[]?
A double free — the heap is corrupted, usually a crash.
What is the difference between an lvalue and an rvalue?
An lvalue has a reusable name; an rvalue is a nameless temporary about to be destroyed.
What does Buffer&& mean and when is it chosen?
An rvalue reference; the move constructor takes it so it is selected only for disposable rvalues.
Does std::move(a) move anything by itself?
No — it is a compile-time cast to rvalue that merely permits a move to be selected.
Why does noexcept matter for a move constructor?
So std::vector will use the move (not fall back to a copy) when it reallocates.