C++ Reactive Programming
上QQ阅读APP看书,第一时间看更新

Smart pointers

Managing object lifetimes has been a problematic area for the C++ programming language. If the developer is not careful, the program can leak memory and will slow down performance. Smart pointers are wrapper classes around a raw pointer where operators such as dereferencing (*) and referencing (->) are overloaded. Smart pointers can do object lifetime management, act as a limited form of garbage collection, free memory, and so on. The Modern C++ language has:

  • unique_ptr<T>
  • shared_ptr<T>
  • weak_ptr<T>

A unique_ptr<T> is a wrapper for a raw pointer where there is exclusive ownership with the wrapper. The following code snippet will demonstrate the use of <unique_ptr>:

//---- Unique_Ptr.cpp
#include <iostream>
#include <deque>#include <memory>
using namespace std;
int main( int argc , char **argv ) {
// Define a Smart Pointer for STL deque container...
unique_ptr< deque<int> > dq(new deque<int>() );
//------ populate values , leverages -> operator
dq->push_front(10); dq->push_front(20);
dq->push_back(23); dq->push_front(16);
dq->push_back(41);
auto dqiter = dq->begin();
while ( dqiter != dq->end())
{ cout << *dqiter << "\n"; dqiter++; }
//------ SmartPointer will free reference
//------ and it's dtor will be called here
return 0;
}

std::shared_ptr is a smart pointer that uses reference counting to keep track of references made to a particular instance of an object. The underlying object is destroyed when the last remaining shared_ptr pointing to it is destroyed or reset:

//----- Shared_Ptr.cpp
#include <iostream>
#include <memory>
#include <stdio.h>
using namespace std;
////////////////////////////////////////
// Even If you pass shared_ptr<T> instance
// by value, the update is visible to callee
// as shared_ptr<T>'s copy constructor reference
// counts to the orgininal instance
//

void foo_byvalue(std::shared_ptr<int> i) { (*i)++;}

///////////////////////////////////////
// passed by reference,we have not
// created a copy.
//
void foo_byreference(std::shared_ptr<int>& i) { (*i)++; }
int main(int argc, char **argv )
{
auto sp = std::make_shared<int>(10);
foo_byvalue(sp);
foo_byreference(sp);
//--------- The output should be 12
std::cout << *sp << std::endl;
}

std:weak_ptr is a container for a raw pointer. It is created as a copy of a shared_ptr. The existence or destruction of weak_ptr copies of a shared_ptr have no effect on the shared_ptr or its other copies. After all copies of a shared_ptr have been destroyed, all weak_ptr copies become empty. The following program demonstrates a mechanism that helps us to detect defunct pointers using weak_ptr:

//------- Weak_Ptr.cpp
#include <iostream>
#include <deque>
#include <memory>

using namespace std;
int main( int argc , char **argv )
{
std::shared_ptr<int> ptr_1(new int(500));
std::weak_ptr<int> wptr_1 = ptr_1;
{
std::shared_ptr<int> ptr_2 = wptr_1.lock();
if(ptr_2)
{
cout << *ptr_2 << endl; // this will be exeucted
}
//---- ptr_2 will go out of the scope
}

ptr_1.reset(); //Memory is deleted.

std::shared_ptr<int> ptr_3= wptr_1.lock();
//-------- Always else part will be executed
//-------- as ptr_3 is nullptr now
if(ptr_3)
cout << *ptr_3 << endl;
else
cout << "Defunct Pointer" << endl;
return 0;
}

Classic C++ had a smart pointer type called auto_ptr and it has been removed from the language standard. One needs to use unique_ptr instead.