What is a smart pointer and when should I use one?
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Do the Java Integer and Double objects have unnece
- Why does const allow implicit conversion of refere
- thread_local variables initialization
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Selecting only the first few characters in a strin
- What exactly do pointers store? (C++)
- Converting glm::lookat matrix to quaternion and ba
- What is the correct way to declare and use a FILE
Definitions provided by Chris, Sergdev and Llyod are correct. I prefer a simpler definition though, just to keep my life simple: A smart pointer is simply a class that overloads the
->
and*
operators. Which means that your object semantically looks like a pointer but you can make it do way cooler things, including reference counting, automatic destruction etc.shared_ptr
andauto_ptr
are sufficient in most cases, but come along with their own set of small idiosyncrasies.Let T be a class in this tutorial Pointers in C++ can be divided into 3 types :
1) Raw pointers :
They hold a memory address to a location in memory. Use with caution , as programs become complex hard to keep track.
Pointers with const data or address { Read backwards }
Pointer to a data type T which is a const. Meaning you cannot change the data type using the pointer. ie
*ptr1 = 19
; will not work. But you can move the pointer. ieptr1++ , ptr1--
; etc will work. Read backwards : pointer to type T which is constA const pointer to a data type T . Meaning you cannot move the pointer but you can change the value pointed to by the pointer. ie
*ptr2 = 19
will work butptr2++ ; ptr2--
etc will not work. Read backwards : const pointer to a type TA const pointer to a const data type T . Meaning you cannot either move the pointer nor can you change the data type pointer to be the pointer. ie .
ptr3-- ; ptr3++ ; *ptr3 = 19;
will not work3) Smart Pointers : {
#include <memory>
}Shared Pointer:
Implemented using reference counting to keep track of how many " things " point to the object pointed to by the pointer. When this count goes to 0 , the object is automatically deleted , ie objected is deleted when all the share_ptr pointing to the object goes out of scope. This gets rid of the headache of having to delete objects which you have allocated using new.
Weak Pointer : Helps deal with cyclic reference which arises when using Shared Pointer If you have two objects pointed to by two shared pointers and there is an internal shared pointer pointing to each others shared pointer then there will be a cyclic reference and the object will not be deleted when shared pointers go out of scope. To solve this , change the internal member from a shared_ptr to weak_ptr. Note : To access the element pointed to by a weak pointer use lock() , this returns a weak_ptr.
See : When is std::weak_ptr useful?
Unique Pointer : Light weight smart pointer with exclusive ownership. Use when pointer points to unique objects without sharing the objects between the pointers.
To change the object pointed to by the unique ptr , use move semantics
References : They can essentially be though of as const pointers, ie a pointer which is const and cannot be moved with better syntax.
See : What are the differences between a pointer variable and a reference variable in C++?
Reference : https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ Thanks to Andre for pointing out this question.
A smart pointer is a class that wraps a 'raw' (or 'bare') C++ pointer, to manage the lifetime of the object being pointed to. There is no single smart pointer type, but all of them try to abstract a raw pointer in a practical way.
Smart pointers should be preferred over raw pointers. If you feel you need to use pointers (first consider if you really do), you would normally want to use a smart pointer as this can alleviate many of the problems with raw pointers, mainly forgetting to delete the object and leaking memory.
With raw pointers, the programmer has to explicitly destroy the object when it is no longer useful.
A smart pointer by comparison defines a policy as to when the object is destroyed. You still have to create the object, but you no longer have to worry about destroying it.
The simplest policy in use involves the scope of the smart pointer wrapper object, such as implemented by
boost::scoped_ptr
orstd::unique_ptr
.Note that
scoped_ptr
instances cannot be copied. This prevents the pointer from being deleted multiple times (incorrectly). You can, however, pass references to it around to other functions you call.Scoped pointers are useful when you want to tie the lifetime of the object to a particular block of code, or if you embedded it as member data inside another object, the lifetime of that other object. The object exists until the containing block of code is exited, or until the containing object is itself destroyed.
A more complex smart pointer policy involves reference counting the pointer. This does allow the pointer to be copied. When the last "reference" to the object is destroyed, the object is deleted. This policy is implemented by
boost::shared_ptr
andstd::shared_ptr
.Reference counted pointers are very useful when the lifetime of your object is much more complicated, and is not tied directly to a particular section of code or to another object.
There is one drawback to reference counted pointers — the possibility of creating a dangling reference:
Another possibility is creating circular references:
To work around this problem, both Boost and C++11 have defined a
weak_ptr
to define a weak (uncounted) reference to ashared_ptr
.UPDATE
This answer is rather old, and so describes what was 'good' at the time, which was smart pointers provided by the Boost library. Since C++11, the standard library has provided sufficient smart pointers types, and so you should favour the use of
std::unique_ptr
,std::shared_ptr
andstd::weak_ptr
.There is also
std::auto_ptr
. It is very much like a scoped pointer, except that it also has the "special" dangerous ability to be copied — which also unexpectedly transfers ownership! It is deprecated in the newest standards, so you shouldn't use it. Use thestd::unique_ptr
instead.The existing answers are good but don't cover what to do when a smart pointer is not the (complete) answer to the problem you are trying to solve.
Among other things (explained well in other answers) using a smart pointer is a possible solution to How do we use a abstract class as a function return type? which has been marked as a duplicate of this question. However, the first question to ask if tempted to specify an abstract (or in fact, any) base class as a return type in C++ is "what do you really mean?". There is a good discussion (with further references) of idiomatic object oriented programming in C++ (and how this is different to other languages) in the documentation of the boost pointer container library. In summary, in C++ you have to think about ownership. Which smart pointers help you with, but are not the only solution, or always a complete solution (they don't give you polymorphic copy) and are not always a solution you want to expose in your interface (and a function return sounds an awful lot like an interface). It might be sufficient to return a reference, for example. But in all of these cases (smart pointer, pointer container or simply returning a reference) you have changed the return from a value to some form of reference. If you really needed copy you may need to add more boilerplate "idiom" or move beyond idiomatic (or otherwise) OOP in C++ to more generic polymorphism using libraries like Adobe Poly or Boost.TypeErasure.
Here's a simple answer for these days of modern C++:
It's a type whose values can be used like pointers, but which provides the additional feature of automatic memory management: When a smart pointer is no longer in use, the memory it points to is deallocated (see also the more detailed definition on Wikipedia).
In code which involves tracking the ownership of a piece of memory, allocating or de-allocating; the smart pointer often saves you the need to do these things explicitly.
std::unique_ptr
when you don't intend to hold multiple references to the same object. For example, use it for a pointer to memory which gets allocated on entering some scope and de-allocated on exiting the scope.std::shared_ptr
when you do want to refer to your object from multiple places - and do not want your object to be de-allocated until all these references are themselves gone.std::weak_ptr
when you do want to refer to your object from multiple places - for those references for which it's ok to ignore and deallocate (so they'll just note the object is gone when you try to dereference).boost::
smart pointers orstd::auto_ptr
except in special cases which you can read up on if you must.Ah, but you really wanted to, admit it.
Mostly in code that is oblivious to memory ownership. This would typically be in functions which get a pointer from someplace else and do not allocate, de-allocate or store a copy of the pointer which outlasts their execution.
Most kinds of smart pointers handle disposing of the pointer-to object for you. It's very handy because you don't have to think about disposing of objects manually anymore.
The most commonly-used smart pointers are
std::tr1::shared_ptr
(orboost::shared_ptr
), and, less commonly,std::auto_ptr
. I recommend regular use ofshared_ptr
.shared_ptr
is very versatile and deals with a large variety of disposal scenarios, including cases where objects need to be "passed across DLL boundaries" (the common nightmare case if differentlibc
s are used between your code and the DLLs).