Browse DevX
Sign up for e-mail newsletters from DevX


Automate Resource Management with shared_ptr-2 : Page 2




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Presenting the Problem
A typical smart pointer wraps a raw pointer to a dynamically allocated object and overloads the operators -> and *. The responsibility for deleting the pointer is delegated to the smart pointer's destructor, thus freeing you from manual—and bug-prone—memory management. The problem, however, is that auto_ptr, the only smart pointer class available in C++98, has peculiar copy and assignment semantics. When you assign an auto_ptr x to another auto_ptr y, not only is the target object modified (as expected) but so is the source object, which becomes null. This behavior makes auto_ptr incompatible with STL containers and algorithms. Let's see how shared_ptr solves this problem.

Author's Note: To use shared_ptr you need to download its sources from Boost. Notice that this Solution adheres to the official TR1 Draft Proposal, which differs slightly from boost::shared_ptr.

Construction and Initialization
shared_ptr's default constructor creates what is known as an empty smart pointer, i.e., an object whose pointer is null. You can assign a valid pointer to it later:

class Foo{ int x; public: explicit Foo(int val=0) :x(val) {} void do_something() {/*..*/} int show_x() const {std::cout<< x<<std::endl; } }; #include <memory> //for shared_ptr using std::tr1::shared_ptr; int main() { shared_ptr<Foo> pf; //pf is an empty shared_ptr //bind a "live" pointer to pf pf=new Foo; pf->do_mesomething(); //using shared_ptr's overloaded -> (*pf).show_x();//using shared_ptr's overloaded * }//pf's destructor called here, destroying Foo

shared_ptr defines a conversion operator to bool. This is useful for testing whether the shared_ptr is empty. To access the raw pointer directly, call get():

if (pf) { //ensure that pf isn't empty before calling get Foo *palias = pf.get(); }

The second shared_ptr constructor takes a pointer to a dynamically allocated object and an optional deleter. The following example defines a deleter and passes its address to shared_ptr's constructor:

void my_deleter(Foo *ptr) { delete ptr; std::cout<< "using custom deleter" <<std::endl; } shared_ptr<Foo> pf (new Foo, my_deleter);

A deleter can be any callable entity: a free function, a function object, etc. When a user-defined deleter d is provided, shared_ptr's destructor calls:


Instead of deleting ptr directly. A custom deleter enables you to bind shared_ptr to a pointer that was allocated in a different DLL, for example.

Certain resources such as file descriptors, synchronization objects, and device contexts require that a special API function be called to release them. Using a custom deleter, shared_ptr can manage such resources elegantly. In the following example, shared_ptr holds a mutex pointer obtained from an API function. When the shared_ptr object is destroyed, the release_mutex() function is called automatically:

//API functions for acquiring and releasing a mutex mutex_t* get_mutex(pid_t pid); int release_mutex(mutex_t* pmx); shared_ptr <mutex_t> pmutex (get_mutex(mypid), release_mutex);

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date