In C++, smart pointers are a feature of the Standard Template Library (STL) that provide the functionality of pointers while also managing memory. They automatically deallocate memory when they're no longer needed, preventing memory leaks. Two common types of smart pointers are std::unique_ptr
and std::shared_ptr
.
In this article, we will delve into these two types of smart pointers, with a focus on the unique feature of custom deleters, using an investment management example.
Unique Pointers
The std::unique_ptr
is a smart pointer that exclusively owns and manages another object through a pointer and disposes of that object when the unique_ptr
is destroyed. A unique_ptr
cannot be copied, but it can be moved to transfer ownership of the managed object.
In the context of our example, we have created several classes representing different types of investments (Investment
, Stock
, Bond
, and RealEstate
).
CancelInvestment
, CancelStock
, CancelBond
, and CancelRealEstate
as custom deleters.uniqueMakeInvestment
function, we create a unique_ptr
that uses a custom deleter (CancelInvestment
) to manage instances of Investment
classes.
A unique_ptr
with a custom deleter has the type of the deleter as part of its type. It's important to note that the deleter does not change the size of the unique_ptr
.
Shared Pointers
A std::shared_ptr
is a smart pointer that retains shared ownership of an object. Multiple shared_ptr
pointers can point to the same object, and the object is destroyed when the last shared_ptr
is destroyed or goes out of scope.
The sharedMakeInvestment
function is similar to the uniqueMakeInvestment
function, but it uses shared_ptr
instead of unique_ptr
.
However, unlike unique_ptr
, the custom deleter is not part of the type of shared_ptr
. This allows more flexibility, as different shared_ptr
instances managing the same object can have different custom deleters.
In the main
function, both types of smart pointers are used:
In this way, the C++ language provides powerful tools for managing memory and object lifetimes with smart pointers, and even allows customization of the deletion process with custom deleters. This is particularly useful in complex applications where memory management is crucial for performance and stability.
#include<iostream> #include<memory> using namespace std; class Investment { public: Investment() { cout << "Investment( " << this << ")" <<endl; } virtual void Type() const { cout << "Investment Type " << endl; } virtual ~Investment() { cout << "~Investment( " << this << ")" <<endl; } }; class Stock:public Investment { public: Stock() { cout << "Stock( " << this << ")" <<endl; } virtual void Type() const override { cout << "Stock Type " << endl; } virtual ~Stock() { cout << "~Stock( " << this << ")" <<endl; } }; class Bond:public Investment { public: Bond() { cout << "Bond( " << this << ")" <<endl; } virtual void Type() const override { cout << "Bond Type " << endl; } virtual ~Bond() { cout << "~Bond( " << this << ")" <<endl; } }; class RealEstate: public Investment { public: RealEstate() { cout << "RealEstate( " << this << ")" <<endl; } virtual void Type() const override{ cout << "RealEstate Type " << endl; } virtual ~RealEstate() { cout << "~RealEstate( " << this << ")" <<endl; } }; auto CancelInvestment = [] (Investment *iv) { cout << "Transfer Investment: (" << iv << ")" << endl; delete iv; }; auto CancelStock = [] (Investment *iv) { cout << "Sale Stock: (" << iv << ")" << endl; delete iv; }; auto CancelBond = [] (Investment *iv) { cout << "Sale Bond: (" << iv << ")" << endl; delete iv; }; auto CancelRealEstate = [] (Investment *iv) { cout << " Rent RealEstate: (" << iv << ")" << endl; delete iv; }; template<typename T> unique_ptr<Investment, decltype(CancelInvestment)> uniqueMakeInvestment( const T type) { switch (type) { case 1: { unique_ptr<Investment, decltype(CancelInvestment)>Inv(new Stock, CancelInvestment); return Inv; } case 2: { unique_ptr<Investment, decltype(CancelInvestment)> Inv(new Bond, CancelInvestment); return Inv; } case 3: { unique_ptr<Investment, decltype(CancelInvestment)> Inv(new RealEstate, CancelInvestment); return Inv; } default: { unique_ptr<Investment, decltype(CancelInvestment)> Inv(new Investment, CancelInvestment); return Inv; } } } template<typename T> shared_ptr<Investment> sharedMakeInvestment( const T type) { switch (type) { case 1: { shared_ptr<Investment>Inv(new Stock, CancelStock); return Inv; } case 2: { shared_ptr<Investment> Inv(new Bond, CancelBond); return Inv; } case 3: { shared_ptr<Investment> Inv(new RealEstate, CancelRealEstate); return Inv; } default: { shared_ptr<Investment> Inv(new Investment, CancelInvestment); return Inv; } } } int main(void) { auto ptrA = move(uniqueMakeInvestment<int>(1)); auto ptrB = sharedMakeInvestment<int>(3); }
No comments:
Post a Comment