Smart Pointers
Types of smart pointers:
- unique pointers (unique_ptr)
- shared pointers (shared_ptr)
- weak pointers (weak_ptr)
Issues with Raw pointers
Memory management:
→ allocation
→ deallocation
→ lifetime management
Potential problems:
→ uninitialized (wild) poitners
→ memory leaks
→ dangling pointers
→ not exception safe
What are Smart Pointers
→ can only point to heap-allocated memory
→ automatically call delete when no longer needed
Create Smart Pointer
#include <memory>
Defined by class templates
- wrapper around a raw pointer
- overloaded operators
- Dereference (*)
- Member selection (→)
- Pointer arithmetic not supported (++,—,etc.)
- can have custom deleters
Syntax for declaring
{
std::smart_pointer<Some_Class> ptr = ...
ptr->method();
cout << (*ptr) << endl;
} // here out of scope
// ptr will be destroyed automatically when
// no longer needed
Types - Unique Pointer
unique_ptr
→ simple smart pointer
unique_ptr<T>
→ points to an object of type T on the heap
→ owns what it points to
→ cannot be assign or copied
→ CAN be moved
→ when the pointer is destroyed, what it points to is automatically destroyed
// creating, initializing and using
{
std::unique_ptr<int> p1 {new int {100} };
std::cout << *p1 << std::endl; // 100
*p1 = 200;
std::cout << *p1 << std::endl; // 200
} // automatically deleted
// some other useful methods
{
std::unique_ptr<int> p1 {new int {100} };
std::cout << p1.get() << std::endl; //0x546388
p1.reset(); // p1 is now nullptr
if (p1)
std::cout << *p1 << std::endl; // won't execute
} // automatically deleted
// unique_ptr - user defined classes
{
std::unique_ptr<Account> p1 {new Account{"Larry"}};
std::cout << *p1 << std::endl; // display account
p1->deposit(1000);
p1->withdraw(500);
} // automatically deleted
// unique_ptr - vectors and move
{
std::vector<std::unique_ptr<int>> vec;
std::unique_ptr<int> ptr {new int{100}};
vec.push_back(ptr); // Error - copy not allowed
vec.push_back(std::move(ptr));
} // automatically deleted
Types - shared pointer
shred_ptr
→ provides shared ownership of heap objects
shared_ptr<T>
→ points to an object of type T on the heap
→ not unique, there can be many shared_pointers pointing to the same object on the heap
→ establishes shared ownership relationship
→ CAN be assigned and copied, can be moved
→ doesn’t support managing arrays by default
→ when the use count is zero, the managed object on the heap is destroyed
// shared_ptr - creating, initializing and using
{
std::shared_ptr<int> p1 {new int {100} };
std::cout << *p1 << std::endl; // 100
*p1 = 200;
std::cout << *p1 << std::enl; // 200
} // automatically deleted
// some other useful methods
{
// use_count - the number of shared_ptr objects managing the heap object
std::shared_ptr<int> p1 {new int {100} };
std::cout << p1.use_count () << std::endl; // 1
std::shared_ptr<int> p2 { p1 }; // shared ownership
std::cout << p1.use_count () << std::endl; // 2
p1.reset(); // decrement the use_count; p1 is nulled out
std::cout << p1.use_count() << std::endl; // 0
std::cout << p2.use_count() << std::endl; // 1
} // automatically deleted
// user defined classes
{
std::shared_ptr<Account> p1 {new Account{"Larry"}};
std::cout << *p1 << std::endl; // display account
p1->deposit(1000);
p1->withdraw(500);
} // automatically deleted
// vectors and move
{
std::vector<std::shared_ptr<int>> vec;
std::shraed_ptr<int> ptr {new int{100}};
vec.push_back(ptr); // OK - copy IS allowed
std:: cout << ptr.use_count() << std::endl; // 2
} //automatically deleted
// make_shared example
{
std::shared_ptr<int> p1 = std::make_shared<int>(100); //use_count: 1
std::shared_ptr<int> p2 { p1 }; //use_count: 2
std::shared_ptr<int> p3;
p3 = p1; //use_count: 3
} // automatically deleted
// use std::make_shared is more efficient
// all 3 pointers point to the SAME object on the heap
// whe the use_count becomes 0 the heap object is deallocated