Department of Engineering

IT Services

C++ Smart Pointers

What are smart pointers? Why do we need them? What's wrong with the old ones?

Old pointers

C++ programmers don't need to use pointers as often as C programmers do. One situation when pointers might be used is in association with new. In the following line

  int * ip= new int;

a pointer is created to some newly allocated memory. Unlike the memory used to create an integer with

  int i;

this memory isn't recycled when the function it's in exits - it has to be explicitly freed using

  delete ip;

If it's not freed, then there's a "memory leak" - the memory can't be used. If a program does this repeatedly, it will run out of space.

With complicated code it's not always easy to ensure that the memory is freed at the right time - too early and you risk a crash if the freed memory is accessed. Also an exception might cause the function to end at a surprising time and the memory won't be freed.

Another problem arises when 2 pointers point to the same block of memory. After

  int * ip= new int;
  int * ip2= ip;

both ip and ip2 point to the same block of memory, so

 delete ip;
 delete ip2;

(freeing the same block of memory twice) might cause trouble.

auto_ptr

For the above (and several other) reasons, people have developed more sophisticated types of pointers ("smart pointers") offering various extra facilities. C++ currently offers only one type, but the next release will offer more, and others are available in the boost library. C++'s auto_ptr deals with the "memory leak" issue, and deals with the "sharing" problem by forbidding sharing. Here's some code -

#include <memory>
#include <iostream>
using namespace std;

class Foo {
public:
  int i;
  void set(int j) {i=j;};
};

int main() {
  auto_ptr<Foo> a1(new Foo);
  a1->set(9);
  cout << a1->i << endl;
  auto_ptr<Foo> a2=a1;
  cout << a2->i << endl;
  cout << a1->i << endl;
  }

a1 points to a newly allocated block of code where an object of type Foo is stored (there's nothing special about Foo - it has an integer and a member function). This memory will automatically be freed when a1 goes out of scope or when there's an exception that bypasses the function's return statements. This solves one problem.

Then the code creates a2 as a copy of a1, but because it doesn't allow sharing, it doesn't just copy a1, it invalidates a1's internal pointer so that only a2 has a valid pointer to the memory. Consequently, if you run the code you should get

9 9 Segmentation fault

In real code you'd check the value of a1.get() first, before trying to access the underlying memory - if a1.get() returns 0, a1 no longer points to anything useful.

Problems

auto_ptrs don't work with arrays, and they're rather restrictive. The next version of C++ will have more types of smart pointers.

References