Smart Pointers

Types of smart pointers:

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