RAII and Smart Pointer in C++
Table of Contents
- Pass pointers in C++
- RAII: Resource Acquisition is Initialization: it means to cleanup in the destructor.
- This applies to raw heap pointers, file handles, mutex, etc.
- The Rule of Three: all three need to be user defined if RAII.
- Destroctor is called even after throw
- The Rule of Three: if not RAII (don't store data or contains only well written Rule of Three classes)
- The Rule of Five:
- The Rule of Four and a half:
- Good examples
Pass pointers in C++
Raw pointer or reference
- it is considered as borrow
- lifetime needs to be guaranteed. (unlike Rust, C++ compiler does not guarantee this for you.)
- raw pointer can be nullptr while reference cannot.
unique_ptr
- transfer ownership (move)
- This is the default in Rust.
shared_ptr
- Shared ownership.
unique_ptr&
or shared_ptr&
- Consider using raw pointer, since the idea is the same.
- Unless you want to do something to the smart ptr itself.
const unique_ptr
or const shared_ptr
- This means the smart ptr object is const, can you cannot modify (e.g. reset) the smart ptr. This is not the smart version of const Raw*.
const unique_ptr&
or const shared_ptr&
- You should use raw pointer. In this case, you cannot even modify the smartptr
RAII: Resource Acquisition is Initialization: it means to cleanup in the destructor.
This applies to raw heap pointers, file handles, mutex, etc.
The Rule of Three: all three need to be user defined if RAII.
- destructor
- copy ctor
- The default will lead to double deletion
- copy assignment: use copy-and-swap to implement it.
- copy: call copy ctor and generate a new object
- swap: swap LHS and the new object and use the new objects' destructor to free the LHS.
Destroctor is called even after throw
The Rule of Three: if not RAII (don't store data or contains only well written Rule of Three classes)
Let compiler generate them.
The Rule of Five:
- all three rules plus
- move ctor
- Destroy RHS
- move assignment
- move: call move ctor: RHS is destroyed.
- swap: same as before, use the destructor of the new object to free LHS.
The Rule of Four and a half:
- All three ctors
- merge copy and move assignment into a value assignment
- since the first thing of these two are creating a copy (through copy or move ctor) anyway
- The half is the swap function.
- Otherwise, the default swap will call move and copy.
Good examples
unique_ptr
: ctor, move ctor and move assignmentshared_ptr
: all fiveunique_lock
ifstream
lock_guard
: just ctor and destructor