SlideShare a Scribd company logo
2
Most read
3
Most read
5
Most read
Smart Pointers in C++
Francesco Casalegno
Raw pointers are dangerous!
● In C++ we use pointers to handle memory that was dynamically allocated with new.
However, raw pointers can be dangerous for many reasons.
2
Person* p = new Person("John", 25);
p->call(); // exception may be thrown here...
delete p; // ... and we never get here!
→ Missing delete causes memory leaks.
This easily happens when exceptions are not correctly handled.
→ Calling delete more than once yields undefined behavior.
Person* p = new Person("John", 25);
Person* q = p;
delete p;
delete q; // undefined behavior: object already deleted!
→ After a delete we get a dangling pointer.
Person* p = new Person[10];
delete[] p; // p still points to the same memory location!
p[0]->call(); // undefined behavior!
p = nullptr; // ok, now p is not dangling any more
Smart Pointers
● You can avoid these drawbacks by using smart pointers.
A smart pointers is a wrapper of a raw pointer providing same functionalities with more safety:
→ same syntax as raw pointers for deferencing: *p, p->val, and p[idx]
→ automatic management of dynamically allocated memory lifetime
→ exception-safe destruction
→ automatically set to nullptr, avoiding dangling pointers
● We have 4 kinds of smart pointers, all defined in the header <memory>
→ std::auto_ptr (from C++98) was a first naive attempt to implement a smart pointer with
exclusive-ownership. It is deprecated from C++11, and removed from the STL from C++14.
→ std::unique_ptr (from C++11) is a smart pointer used for exclusive-ownership
that can be copied only with move semantics.
→ std::shared_ptr (from C++11) is a smart pointer used for shared-ownership with automatic
garbage collection based on a reference count.
→ std::weak_ptr (from C++11) is a smart pointer used for observing without owning. It is similar to
std::shared_ptr, but it does not contribute to the reference count. 3
std::auto_ptr
● An auto_ptr provides exclusive ownership for a pointer that it holds. When auto_ptr is destroyed, the
object pointed is also automatically destroyed through a call to delete.
● Introduced pre C++11, so no move semantics: how to copy the pointer while keeping exclusivity?
Workaround: c-tor and assignment receive by value and steal the ownership!
● This (deprecated) smart pointers clearly had many issues:
→ when it gets destroyed it always call delete, so no dynamic arrays (delete[])
→ copy / move c-tor and assignment take arguments by non-const argument (same behavior for
lval or rval) and have strange side-effects (stealing ownership): does not respect the natural
requirements of CopyConstructible and CopyAssignable
→ therefore it cannot be used in STL containers (pre C++11) or it is deprecated to do it (C++11)
... If you have C++11, then just use std::unique_ptr instead!
4
{
std::auto_ptr<Person> p(new Person("John", 25));
p->call(); // if exception is thrown, delete is automatically called
} // here p goes out of scope, delete is automatically called
std::auto_ptr<Person> p("John", 25);
std::auto_ptr<Person> q = p; // copy c-tor: q points to object, p is nullptr!
p = q; // copy assignment: p points to object, q is nullptr!
std::unique_ptr
● A unique_prt u provides exclusive ownership for the pointer p that it holds. When u is destroyed, the
object pointed by p is disposed using p’s associated deleter (custom of default delete/delete[] )
● Main difference with respect to auto_prt:
→ copy c-tor and assignment are deleted, so that copying from lvalue is not allowed
→ move c-tor and assignment are implemented to allow ownership change by natural move semantics
5
std::unique_ptr<Person> p(new Person("John", 25));
std::unique_ptr<Person> q = p; // compiler error! copy c-tor is deleted
std::unique_ptr<Person> q = std::move(p); // ok, move c-tor called
p = q; // compiler error! copy assignment is deleted
p = std::move(q); // ok, move assignment called
● Important features:
→ template specialization unique_prt<T[]> to handle dynamic arrays
→ copy from lvalue is deleted, copy from rvalue is implemented using move semantics
so that it can suitably work in a STL container
→ custom deleter can be provided if needed
→ pretty simple wrapper implementation, so no overhead in memory (unless custom deleter) or runtime
→ easy conversion to shared_ptr
John
Alice
std::unique_ptr – useful methods
● Observes
● Modifiers
6
pointer get() const;
→ returns a pointer to the managed object
deleter& get_deleter();
→ returns a reference to the deleter object used for the disposal of the managed object
pointer release();
→ releases ownership by returning the managed object + setting the internal pointer to nullptr
void reset( pointer ptr = pointer() );
→ replaces the internal pointer with ptr, and disposes of the previously owned object by calling
the deleter
std::shared_ptr
● A shared_ptr provides shared ownership: many pointers may own the same object and the last one
to survive is responsible of its disposal through the deleter.
● This garbage collection mechanism is based on a reference counter contained in a control block.
Each new shared owner copies the pointer to the control block and increases the count by 1.
● Important features:
→ until C++17 no template specialization shared_prt<T[]> to handle dynamic arrays
→ custom deleter and custom allocator (for internal data allocation) can be provided if needed
→ it is CopyConstructible and CopyAssignable, so it can work in a STL container
→ non-trivial implementation and memory overhead (typically 2 pointers: object itself + ctrl block)
→ many operations require atomic (thread safety!) update of ref_counter, which may be slow
→ aliasing c-tor allows to share ownership on an object and point elsewhere (e.g. object’s member)
7
std::shared_ptr p(new Person("John", 25)); // construction: ref_counter=1
std::shared_ptr q = p; // new owner: ref_counter=2
std::shared_ptr r = std::move(p); // r steals ownership: ref_counter=2
p.reset(new Person("Alice", 23)); // p resets managed object: ref_counter=1
r = nullptr; // move assign to nullptr: ref_counter=0,
and deleter is called!
ptr to obj
shared_ptr
“John”
25
ref_counter
custom del
custom alloc
ptr to ctrl
John
object controller
std::shared_ptr – useful methods
● Observes
● Modifiers
8
T* get() const;
→ returns stored pointer
long use_count() const;
→ returns the number of shared pointers managing current object
bool unique() const noexcept;
→ returns whether use_count()==1
template< class Y > void reset( Y* ptr );
→ replaces the managed object with the one pointed by ptr, and disposes of the previously
owned object by calling the deleter
std::weak_ptr
● A weak_ptr tracks without owning a pointer to an object managed by a shared_ptr. It implements weak
ownership: the object needs to be accessed only if still exists, and it may be deleted by others.
If we need to access the object we have to convert it into a shared_ptr.
● Used as observer to determine if the pointer is dangling before converting to shared_ptr and using it.
Typical use cases are implementing a cache and breaking cycles:
Example with cycles: how to do if A and C share ownership on B, but B must also point to A?
→ raw ptr: if A gets destroyed, B has no way to know it and its pointer dangles
→ shared_ptr: if C gets destroyed we still have a cycle and therefore A and B are never deleted!
The only reasonable solution is weak_ptr!
● Important features:
→ cannot directly access the pointed object: *p, p->val, or p[idx] are not implemented!
→ convert to shared_ptr (after check for dangling!) when you need to access object
→ implemented very similar to shared_ptr, but no contribution to ref_counter update
→ same memory overhead as shared_ptr, and performance penalty for accessing due to
conversion
9
A B C
John Alice
std::weak_ptr – useful methods
● Observes
● Modifiers
10
long use_count() const;
→ returns the number of shared pointers managing current object
bool expired() const;
→ check if use_count()==0
std::shared_ptr<T> lock() const;
→ creates a new shared_ptr owning the managed object
template< class Y > void reset();
→ releases the reference to the managed object
Avoid new, use factories
● Using std::unique_ptr and std::shared_ptr avoid memory leaks through automatic life-time
management and garbage collection. Basically, we do not need to call delete any more!
● However, we still need to call new operator when we call the constructor. This is bad for 2 reasons.
→ Since function arguments can be evaluated in any order, if throw() occurs we may have a leak
→ For shared_ptr, calling the c-tor with new inside causes a double allocation (one for the
object itself, one for the control block) and therefore time penalty
● C++ provides us with factories that fix this issue:
→ std::make_unique (from C++14, but implementation is trivial)
→ std::make_shared (from C++11)
→ std::allocate_shared (from C++11, same as make_shared but with custom memory allocator)
● There is a caveat with make_shared. As the allocation is made for object + ctrl block together, as long
as a weak_ptr needs the ctrl block to be alive, the object cannot be destroyed!
11
foo(std::unique_ptr<double[]>(new double[10]), bar(42));
// argument evaluation could be: i) new double[10], ii) bar(42) iii) unique_ptr c-tor
// if at ii) bar(42) throws, no one will call delete[] on the memory allocated during i) !!
Do we still need raw pointers?
● Smart pointers implement automatic management of dynamically allocated memory.
This comes with little overhead, or even no overhead as in the case of unique_ptr.
● However, there are still cases when raw pointers are needed.
→ when the pointer really just mean an address, not ownership of an object
→ to implement iterators
→ to handle an array decaying into a pointer
→ when working with legacy code (e.g. pre-C++11)
→ when passing arguments by address to modify their content
12
Take-Home Message
1. Raw ptrs are dangerous when handling dynamically allocated memory.
Smart ptrs are a safe alternative, with little or no overhead, providing automatic management of owned objects.
2. Use std::unique_ptr to implement exclusive ownership and transfer it using std::move.
3. Use std::shared_ptr to implement shared ownership: the garbage collector mechanism (based on a ref_counter in the
control block) deletes the object when no more share pointers owns it. Be aware of the overhead of this choice.
4. Use std::weak_ptr to observe without owning an object managed by a shared_ptr, and in particular to solve reference
cycles. Accessing the object is possible through a conversion to shared_ptr, which causes some overhead.
5. In general it is a good idea to use make_shared and make_unique whenever possible in order to avoid memory leaks
and provide exception safety, as well as to avoid double memory allocation for shared_ptr.
13
Main References:
→ Meyers, Scott. Effective modern C++: 42 specific ways to improve your use of C++ 11 and C++ 14. " O'Reilly Media, Inc.", 2014.
→ ISO C++ Standards ISO/IEC 14882:2011 and ISO/IEC 14882:2014

More Related Content

PPTX
Inheritance in c++
PPTX
Programming Language Evolution
PDF
C++ Unit Test with Google Testing Framework
PPTX
[Webinar] Qt Test-Driven Development Using Google Test and Google Mock
 
PPT
Spanning Tree Protocol
PDF
Git basics for beginners
PPT
PPTX
Strings in c++
Inheritance in c++
Programming Language Evolution
C++ Unit Test with Google Testing Framework
[Webinar] Qt Test-Driven Development Using Google Test and Google Mock
 
Spanning Tree Protocol
Git basics for beginners
Strings in c++

What's hot (20)

PPTX
Smart pointers
PPT
Memory allocation in c
PPTX
Oop c++class(final).ppt
PDF
C++ Files and Streams
PPT
Stl Containers
PPTX
File in C language
PPTX
Templates in C++
PPT
Structure of C++ - R.D.Sivakumar
PPTX
Pointer in C++
PDF
Python programming : Classes objects
PDF
Python functions
PDF
PPTX
CONDITIONAL STATEMENT IN C LANGUAGE
PPTX
Pointers in c++
PPT
PDF
Object oriented programming c++
PPT
File handling in C++
PPS
String and string buffer
PDF
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
Smart pointers
Memory allocation in c
Oop c++class(final).ppt
C++ Files and Streams
Stl Containers
File in C language
Templates in C++
Structure of C++ - R.D.Sivakumar
Pointer in C++
Python programming : Classes objects
Python functions
CONDITIONAL STATEMENT IN C LANGUAGE
Pointers in c++
Object oriented programming c++
File handling in C++
String and string buffer
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
Ad

Similar to Smart Pointers in C++ (20)

PDF
smart pointers are unique concept to avoid memory leakage
PDF
(3) cpp abstractions more_on_user_defined_types
PDF
(4) cpp abstractions references_copies_and_const-ness
PDF
Cpp17 and Beyond
PDF
C++11 smart pointer
PDF
Where destructors meet threads
PDF
One Careful Owner
PDF
CS225_Prelecture_Notes 2nd
PDF
Take advantage of C++ from Python
PPTX
C++11: Feel the New Language
PDF
L6
PPT
Handling Exceptions In C &amp; C++ [Part B] Ver 2
PPTX
Object orinted programming lecture| Variables
PDF
C++11: Rvalue References, Move Semantics, Perfect Forwarding
PDF
(5) cpp dynamic memory_arrays_and_c-strings
PDF
C++_notes.pdf
PDF
(5) cpp abstractions essential_operators
PPTX
smart.pptxsmart.pptxsmart.pptxsmart.pptxsmart.pptx
PPTX
smart.pptxsmart.pptxsmart.pptxsmart.pptxsmart.pptx
TXT
Advance C++notes
smart pointers are unique concept to avoid memory leakage
(3) cpp abstractions more_on_user_defined_types
(4) cpp abstractions references_copies_and_const-ness
Cpp17 and Beyond
C++11 smart pointer
Where destructors meet threads
One Careful Owner
CS225_Prelecture_Notes 2nd
Take advantage of C++ from Python
C++11: Feel the New Language
L6
Handling Exceptions In C &amp; C++ [Part B] Ver 2
Object orinted programming lecture| Variables
C++11: Rvalue References, Move Semantics, Perfect Forwarding
(5) cpp dynamic memory_arrays_and_c-strings
C++_notes.pdf
(5) cpp abstractions essential_operators
smart.pptxsmart.pptxsmart.pptxsmart.pptxsmart.pptx
smart.pptxsmart.pptxsmart.pptxsmart.pptxsmart.pptx
Advance C++notes
Ad

More from Francesco Casalegno (7)

PDF
DVC - Git-like Data Version Control for Machine Learning projects
PDF
Ordinal Regression and Machine Learning: Applications, Methods, Metrics
PDF
Recommender Systems
PDF
Markov Chain Monte Carlo Methods
PDF
Hyperparameter Optimization for Machine Learning
PDF
Confidence Intervals––Exact Intervals, Jackknife, and Bootstrap
PDF
[C++] The Curiously Recurring Template Pattern: Static Polymorphsim and Expre...
DVC - Git-like Data Version Control for Machine Learning projects
Ordinal Regression and Machine Learning: Applications, Methods, Metrics
Recommender Systems
Markov Chain Monte Carlo Methods
Hyperparameter Optimization for Machine Learning
Confidence Intervals––Exact Intervals, Jackknife, and Bootstrap
[C++] The Curiously Recurring Template Pattern: Static Polymorphsim and Expre...

Recently uploaded (20)

PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
Getting Started with Data Integration: FME Form 101
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
Encapsulation theory and applications.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Electronic commerce courselecture one. Pdf
PDF
Approach and Philosophy of On baking technology
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
SOPHOS-XG Firewall Administrator PPT.pptx
PPTX
Spectroscopy.pptx food analysis technology
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
Assigned Numbers - 2025 - Bluetooth® Document
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Getting Started with Data Integration: FME Form 101
“AI and Expert System Decision Support & Business Intelligence Systems”
NewMind AI Weekly Chronicles - August'25-Week II
Encapsulation theory and applications.pdf
Network Security Unit 5.pdf for BCA BBA.
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Encapsulation_ Review paper, used for researhc scholars
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Spectral efficient network and resource selection model in 5G networks
Electronic commerce courselecture one. Pdf
Approach and Philosophy of On baking technology
Digital-Transformation-Roadmap-for-Companies.pptx
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
SOPHOS-XG Firewall Administrator PPT.pptx
Spectroscopy.pptx food analysis technology
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
A comparative analysis of optical character recognition models for extracting...
Assigned Numbers - 2025 - Bluetooth® Document

Smart Pointers in C++

  • 1. Smart Pointers in C++ Francesco Casalegno
  • 2. Raw pointers are dangerous! ● In C++ we use pointers to handle memory that was dynamically allocated with new. However, raw pointers can be dangerous for many reasons. 2 Person* p = new Person("John", 25); p->call(); // exception may be thrown here... delete p; // ... and we never get here! → Missing delete causes memory leaks. This easily happens when exceptions are not correctly handled. → Calling delete more than once yields undefined behavior. Person* p = new Person("John", 25); Person* q = p; delete p; delete q; // undefined behavior: object already deleted! → After a delete we get a dangling pointer. Person* p = new Person[10]; delete[] p; // p still points to the same memory location! p[0]->call(); // undefined behavior! p = nullptr; // ok, now p is not dangling any more
  • 3. Smart Pointers ● You can avoid these drawbacks by using smart pointers. A smart pointers is a wrapper of a raw pointer providing same functionalities with more safety: → same syntax as raw pointers for deferencing: *p, p->val, and p[idx] → automatic management of dynamically allocated memory lifetime → exception-safe destruction → automatically set to nullptr, avoiding dangling pointers ● We have 4 kinds of smart pointers, all defined in the header <memory> → std::auto_ptr (from C++98) was a first naive attempt to implement a smart pointer with exclusive-ownership. It is deprecated from C++11, and removed from the STL from C++14. → std::unique_ptr (from C++11) is a smart pointer used for exclusive-ownership that can be copied only with move semantics. → std::shared_ptr (from C++11) is a smart pointer used for shared-ownership with automatic garbage collection based on a reference count. → std::weak_ptr (from C++11) is a smart pointer used for observing without owning. It is similar to std::shared_ptr, but it does not contribute to the reference count. 3
  • 4. std::auto_ptr ● An auto_ptr provides exclusive ownership for a pointer that it holds. When auto_ptr is destroyed, the object pointed is also automatically destroyed through a call to delete. ● Introduced pre C++11, so no move semantics: how to copy the pointer while keeping exclusivity? Workaround: c-tor and assignment receive by value and steal the ownership! ● This (deprecated) smart pointers clearly had many issues: → when it gets destroyed it always call delete, so no dynamic arrays (delete[]) → copy / move c-tor and assignment take arguments by non-const argument (same behavior for lval or rval) and have strange side-effects (stealing ownership): does not respect the natural requirements of CopyConstructible and CopyAssignable → therefore it cannot be used in STL containers (pre C++11) or it is deprecated to do it (C++11) ... If you have C++11, then just use std::unique_ptr instead! 4 { std::auto_ptr<Person> p(new Person("John", 25)); p->call(); // if exception is thrown, delete is automatically called } // here p goes out of scope, delete is automatically called std::auto_ptr<Person> p("John", 25); std::auto_ptr<Person> q = p; // copy c-tor: q points to object, p is nullptr! p = q; // copy assignment: p points to object, q is nullptr!
  • 5. std::unique_ptr ● A unique_prt u provides exclusive ownership for the pointer p that it holds. When u is destroyed, the object pointed by p is disposed using p’s associated deleter (custom of default delete/delete[] ) ● Main difference with respect to auto_prt: → copy c-tor and assignment are deleted, so that copying from lvalue is not allowed → move c-tor and assignment are implemented to allow ownership change by natural move semantics 5 std::unique_ptr<Person> p(new Person("John", 25)); std::unique_ptr<Person> q = p; // compiler error! copy c-tor is deleted std::unique_ptr<Person> q = std::move(p); // ok, move c-tor called p = q; // compiler error! copy assignment is deleted p = std::move(q); // ok, move assignment called ● Important features: → template specialization unique_prt<T[]> to handle dynamic arrays → copy from lvalue is deleted, copy from rvalue is implemented using move semantics so that it can suitably work in a STL container → custom deleter can be provided if needed → pretty simple wrapper implementation, so no overhead in memory (unless custom deleter) or runtime → easy conversion to shared_ptr John Alice
  • 6. std::unique_ptr – useful methods ● Observes ● Modifiers 6 pointer get() const; → returns a pointer to the managed object deleter& get_deleter(); → returns a reference to the deleter object used for the disposal of the managed object pointer release(); → releases ownership by returning the managed object + setting the internal pointer to nullptr void reset( pointer ptr = pointer() ); → replaces the internal pointer with ptr, and disposes of the previously owned object by calling the deleter
  • 7. std::shared_ptr ● A shared_ptr provides shared ownership: many pointers may own the same object and the last one to survive is responsible of its disposal through the deleter. ● This garbage collection mechanism is based on a reference counter contained in a control block. Each new shared owner copies the pointer to the control block and increases the count by 1. ● Important features: → until C++17 no template specialization shared_prt<T[]> to handle dynamic arrays → custom deleter and custom allocator (for internal data allocation) can be provided if needed → it is CopyConstructible and CopyAssignable, so it can work in a STL container → non-trivial implementation and memory overhead (typically 2 pointers: object itself + ctrl block) → many operations require atomic (thread safety!) update of ref_counter, which may be slow → aliasing c-tor allows to share ownership on an object and point elsewhere (e.g. object’s member) 7 std::shared_ptr p(new Person("John", 25)); // construction: ref_counter=1 std::shared_ptr q = p; // new owner: ref_counter=2 std::shared_ptr r = std::move(p); // r steals ownership: ref_counter=2 p.reset(new Person("Alice", 23)); // p resets managed object: ref_counter=1 r = nullptr; // move assign to nullptr: ref_counter=0, and deleter is called! ptr to obj shared_ptr “John” 25 ref_counter custom del custom alloc ptr to ctrl John object controller
  • 8. std::shared_ptr – useful methods ● Observes ● Modifiers 8 T* get() const; → returns stored pointer long use_count() const; → returns the number of shared pointers managing current object bool unique() const noexcept; → returns whether use_count()==1 template< class Y > void reset( Y* ptr ); → replaces the managed object with the one pointed by ptr, and disposes of the previously owned object by calling the deleter
  • 9. std::weak_ptr ● A weak_ptr tracks without owning a pointer to an object managed by a shared_ptr. It implements weak ownership: the object needs to be accessed only if still exists, and it may be deleted by others. If we need to access the object we have to convert it into a shared_ptr. ● Used as observer to determine if the pointer is dangling before converting to shared_ptr and using it. Typical use cases are implementing a cache and breaking cycles: Example with cycles: how to do if A and C share ownership on B, but B must also point to A? → raw ptr: if A gets destroyed, B has no way to know it and its pointer dangles → shared_ptr: if C gets destroyed we still have a cycle and therefore A and B are never deleted! The only reasonable solution is weak_ptr! ● Important features: → cannot directly access the pointed object: *p, p->val, or p[idx] are not implemented! → convert to shared_ptr (after check for dangling!) when you need to access object → implemented very similar to shared_ptr, but no contribution to ref_counter update → same memory overhead as shared_ptr, and performance penalty for accessing due to conversion 9 A B C John Alice
  • 10. std::weak_ptr – useful methods ● Observes ● Modifiers 10 long use_count() const; → returns the number of shared pointers managing current object bool expired() const; → check if use_count()==0 std::shared_ptr<T> lock() const; → creates a new shared_ptr owning the managed object template< class Y > void reset(); → releases the reference to the managed object
  • 11. Avoid new, use factories ● Using std::unique_ptr and std::shared_ptr avoid memory leaks through automatic life-time management and garbage collection. Basically, we do not need to call delete any more! ● However, we still need to call new operator when we call the constructor. This is bad for 2 reasons. → Since function arguments can be evaluated in any order, if throw() occurs we may have a leak → For shared_ptr, calling the c-tor with new inside causes a double allocation (one for the object itself, one for the control block) and therefore time penalty ● C++ provides us with factories that fix this issue: → std::make_unique (from C++14, but implementation is trivial) → std::make_shared (from C++11) → std::allocate_shared (from C++11, same as make_shared but with custom memory allocator) ● There is a caveat with make_shared. As the allocation is made for object + ctrl block together, as long as a weak_ptr needs the ctrl block to be alive, the object cannot be destroyed! 11 foo(std::unique_ptr<double[]>(new double[10]), bar(42)); // argument evaluation could be: i) new double[10], ii) bar(42) iii) unique_ptr c-tor // if at ii) bar(42) throws, no one will call delete[] on the memory allocated during i) !!
  • 12. Do we still need raw pointers? ● Smart pointers implement automatic management of dynamically allocated memory. This comes with little overhead, or even no overhead as in the case of unique_ptr. ● However, there are still cases when raw pointers are needed. → when the pointer really just mean an address, not ownership of an object → to implement iterators → to handle an array decaying into a pointer → when working with legacy code (e.g. pre-C++11) → when passing arguments by address to modify their content 12
  • 13. Take-Home Message 1. Raw ptrs are dangerous when handling dynamically allocated memory. Smart ptrs are a safe alternative, with little or no overhead, providing automatic management of owned objects. 2. Use std::unique_ptr to implement exclusive ownership and transfer it using std::move. 3. Use std::shared_ptr to implement shared ownership: the garbage collector mechanism (based on a ref_counter in the control block) deletes the object when no more share pointers owns it. Be aware of the overhead of this choice. 4. Use std::weak_ptr to observe without owning an object managed by a shared_ptr, and in particular to solve reference cycles. Accessing the object is possible through a conversion to shared_ptr, which causes some overhead. 5. In general it is a good idea to use make_shared and make_unique whenever possible in order to avoid memory leaks and provide exception safety, as well as to avoid double memory allocation for shared_ptr. 13 Main References: → Meyers, Scott. Effective modern C++: 42 specific ways to improve your use of C++ 11 and C++ 14. " O'Reilly Media, Inc.", 2014. → ISO C++ Standards ISO/IEC 14882:2011 and ISO/IEC 14882:2014