Smart pointer

From Wikipedia, the free encyclopedia

In computer science, a smart pointer is an abstract data type that simulates a pointer while providing additional features, such as automatic memory management or bounds checking. These additional features are intended to reduce bugs caused by the misuse of pointers while retaining efficiency. Smart pointers typically keep track of the memory they point to. They may also be used to manage other resources, such as network connections and file handles.

Misuse of pointers is a major source of bugs. Smart pointers prevent most situations of memory leaks by making the resource deallocation automatic. The resource controlled by a smart pointer is automatically destroyed when the last (or only) owner of the resource is destroyed, for example because it goes out of scope. Smart pointers also eliminate dangling pointers by postponing destruction until the resource is no longer in use.

Several types of smart pointers exist. Some work with reference counting, others by assigning ownership of the object to a single pointer. If the language supports automatic garbage collection (for instance, Java or C#), then smart pointers are unnecessary for memory management, but may still be useful in managing other resources.

C++ smart pointers

In C++, smart pointers may be implemented as a template class that mimics, by means of operator overloading, the behaviour of traditional (raw) pointers, (e.g. dereferencing, assignment) while providing additional memory management algorithms.

Smart pointers can facilitate intentional programming by expressing the use of a pointer in the type itself. For example, if a C++ function returns a pointer, there is no way to know whether the caller should delete the memory pointed to when the caller is finished with the information.

some_type* ambiguous_function(); // What should be done with the result?

Traditionally, this has been solved with comments, but this can be error-prone. The potential problems associated with this use can be mitigated by instead returning a unique_ptr,

unique_ptr<some_type> obvious_function1();

The function makes explicit that the caller will take ownership of the result. Furthermore, no memory will be leaked if the caller does nothing. Prior to C++11, unique_ptr can be replaced with auto_ptr.

unique_ptr

C++11 provides std::unique_ptr, defined in the header <memory>.[1]

The copy constructor and assignment operators of std::auto_ptr do not actually copy the stored pointer. Instead, they transfer it, leaving the previous std::auto_ptr object empty. This was one way to implement strict ownership, so that only one auto_ptr object could own the pointer at any given time. This means that auto_ptr should not be used where copy semantics are needed.[2]

C++11 provides support for move semantics; it allows for the explicit support of transferring values as a different operation from copying them. C++11 also provides support for explicitly preventing an object from being copied. Since std::auto_ptr already existed with its copy semantics, it could not be upgraded to be a move-only pointer without breaking backwards compatibility with existing code. Therefore, C++11 introduced a new pointer type: std::unique_ptr.

This pointer type has its copy constructor and assignment operator explicitly deleted; it cannot be copied. It can be moved using std::move, which allows one unique_ptr object to transfer ownership to another.

std::unique_ptr<int> p1(new int(5));
std::unique_ptr<int> p2 = p1; //Compile error.
std::unique_ptr<int> p3 = std::move(p1); //Transfers ownership. p3 now owns the memory and p1 is rendered invalid.
 
p3.reset(); //Deletes the memory.
p1.reset(); //Does nothing.

std::auto_ptr is still available, but it is deprecated under C++11.

shared_ptr and weak_ptr

C++11 incorporates shared_ptr and weak_ptr, based on versions used by the Boost libraries.[citation needed] TR1 first introduced them to the standard, but C++11 gives them additional functionality in line with the Boost version.

std::shared_ptr represents reference-counted ownership of a pointer. Each copy of the same shared_ptr owns the same pointer. That pointer will only be freed if all instances of the shared_ptr in the program are destroyed.

std::shared_ptr<int> p1(new int(5));
std::shared_ptr<int> p2 = p1; //Both now own the memory.
 
p1.reset(); //Memory still exists, due to p2.
p2.reset(); //Deletes the memory, since no one else owns the memory.

A std::shared_ptr uses reference counting, so circular references are potentially a problem. To break up cycles, std::weak_ptr can be used to access the stored object. The stored object will be deleted if the only references to the object are weak_ptr references. weak_ptr therefore does not ensure that the object will continue to exist, but it can ask for the resource.

std::shared_ptr<int> p1(new int(5));
std::weak_ptr<int> wp1 = p1; //p1 owns the memory.
 
{
  std::shared_ptr<int> p2 = wp1.lock(); //Now p1 and p2 own the memory.
  if(p2) // As p2 is initialized from a weak pointer, you have to check if the memory still exists!
  { 
    //Do something with p2
  }
} //p2 is destroyed. Memory is owned by p1.
 
p1.reset(); //Memory is deleted.
 
std::shared_ptr<int> p3 = wp1.lock(); //Memory is gone, so we get an empty shared_ptr.
if(p3)
{
  //Will not execute this.
}

Concurrency guarantees

Multiple threads can safely access different shared_ptr and weak_ptr objects that point to the same object simultaneously.[3]

The referenced object itself needs to be protected separately to ensure thread safety.

See also

  • RAII (Resource Acquisition Is Initialization)
  • auto_ptr
  • Opaque pointer
  • Reference
  • The Boost library includes boost::intrusive_ptr,[4] a reference-counting and intrusively counted smart pointer implementation for C++.

References

  1. ISO 14882:2011 20.7.1
  2. boost::shared_ptr thread safety (does not formally cover std::shared_ptr, but is believed to have the same threading limitations)
  3. http://www.boost.org/doc/libs/1_52_0/libs/smart_ptr/intrusive_ptr.html

External links

This article is issued from Wikipedia. The text is available under the Creative Commons Attribution/Share Alike; additional terms may apply for the media files.