Monday 1 June 2009

A look at Smart Pointers

There is lot of confucion, misconceptions and misunderstanding regarding smart pointers. After looking at various books and tutorials, i got quite confused till I managed to figure out what they exactly are:

Smart pointers are objects that look and feel like pointers, but are smarter.

To look and feel like pointers, smart pointers need to have the same interface that pointers do: they need to support pointer operations like dereferencing (operator *) and indirection (operator ->). An object that looks and feels like something else is called a proxy object, or just proxy.

To be smarter than regular pointers, smart pointers need to do things that regular pointers don't. What could these things be? Probably the most common bugs in C++ (and C) are related to pointers and memory management: dangling pointers, memory leaks, allocation failures and other joys. Having a smart pointer take care of these things.

The simplest example of a smart pointer is auto_ptr, which is included in the standard C++ library. You can find it in the header , or take a look at Scott Meyers' auto_ptr implementation. Here is part of auto_ptr's implementation, to illustrate what it does:

template <class T> class auto_ptr
{

T* ptr;
public
:
explicit
auto_ptr(T* p = 0) : ptr(p) {}
~
auto_ptr() {delete ptr;}
T& operator*() {return *ptr;}
T* operator->() {return ptr;}
// ...
};

As you can see, auto_ptr is a simple wrapper around a regular pointer. It forwards all meaningful operations to this pointer (dereferencing and indirection). Its smartness in the destructor: the destructor takes care of deleting the pointer.

Lets look at a proper example:

#include<iostream>
#include<memory>


using namespace
std;

class
A
{

public
:
int
*data;
string name;
A(string n): name(n)
{

cout<<"Constructor of A = "<<name.c_str()<<" called "<<endl;
data = new(int);
};

A(string n, int x): name(n)
{

cout<<"Overloaded Constructor of A = "<<name.c_str()<<" called "<<endl;
data = new(int);
*
data = x;
};
~
A()
{

cout<<"Destructor of A = "<<name.c_str()<<" called "<<endl;
delete
(data);
data = this->data;
data = NULL;
}

A* operator ->() { return this;};
};


void
someFunc()
{

auto_ptr<A> a1(new A("a1"));
cout<<"Enter a number and press enter: ";
cin >> (*a1->data);
cout << "a1->data = "<<*a1->data<<endl;

A a2("a2",25);
A *a3 = new A("a3");
}


int
main()
{

cout<<"Before SomeFunc()"<<endl;
someFunc();
cout<<"After SomeFunc()"<<endl;
return
0;
}
The output is as follows:


As you have probably noticed, the instance a3 is never deleted and will cause memory leaks. Using smart pointer would automatically delete the instance a3 and the memory associated with it.

You can read Smart Pointers in much more detail at the References below.

References:
http://ootips.org/yonat/4dev/smart-pointers.html
http://www.geekpedia.com/tutorial47_Smart-Pointers---Part-1.html
http://www.geekpedia.com/tutorial59_Smart-Pointers---Part-II.html

No comments:

Post a Comment