Can someone explain smart pointers in plain English? - c++

Today I was asked about smart pointers in C++, and I can't find anywhere useful information about it..
Please, can someone tell:
What is smart pointers?
When do you need it?
Do you have any example where smart pointers is actually useful?
Thank you!

Primarily, smart pointers help you to:
Avoid leaks when exceptions are thrown. When an exception is thrown, you don't want any objects that are allocated earlier in the try block to be leaked. By wrapping them in smart pointers, which will be destroyed when the try block is exited, those objects will get properly destroyed.
Manage lifetime by reference counting owners to objects (i.e., the last one to destroy its smart pointer referencing a particular object actually deallocates the object). This is especially helpful in loosely coupled scenarios where it is not clear at what time the object should be destroyed, because users of the object do not know about each other.
A good example of where smart pointers are useful:
A vector of pointers to objects. By
making it a vector of shared pointers,
for example, the objects will
automatically be deallocated when the
vector is destroyed and/or objects are
removed. This automates object lifetime management and helps the user of the container avoid memory leaks.

Excerpt from Boost Smart Pointers (smart_ptr) lib:
Smart pointers are objects which store
pointers to dynamically allocated
(heap) objects. They behave much like
built-in C++ pointers except that they
automatically delete the object
pointed to at the appropriate time.
Smart pointers are particularly useful
in the face of exceptions as they
ensure proper destruction of
dynamically allocated objects. They
can also be used to keep track of
dynamically allocated objects shared
by multiple owners.
Conceptually, smart pointers are seen
as owning the object pointed to, and
thus responsible for deletion of the
object when it is no longer needed.

Smart pointers handle their own memory management by keeping track of how many references point to the memory. Once there are 0 references, it deletes the memory for you. Makes memory management easier.

Smart pointer general refers to a class that behaves like a pointer. You can use the class to store a pointer to memory that you allocate, and access data through the pointer.
The advantage is that, when used inside functions and methods, the smart pointer can be made to automatically deallocate the memory once the variable goes out of scope. Otherwise, this is a prime opportunity for a memory leak when functions fail to free all allocated memory.
For an example, check out http://msdn.microsoft.com/en-us/library/txda4x5t(VS.80).aspx.

A smart pointer is an object that dynamically allocates memory for the thing that it points to, and when the smart pointer goes out of scope it automatically deallocates the memory for the thing that it points to. It's useful when you want something that's deallocated when it goes out of scope, but that's too big to put on the stack (or has other issues that prevent it from being able to be put on the stack).

A smart pointer essentially manages memory allocated on the heap with an object allocated on the stack.
Because objects allocated on the stack have a fixed lifetime (i.e. within the scope they are declared) deallocation of the heap memory is deterministic and guaranteed to happen.

Smart pointers are basically objects that perform functions similar to pointers
they are used to lessen the allocation and deallocation time. For C++ one common example would be of auto_ptr

Related

C++: Does vector of pointer elements automatically deallocate dynamic memory pointed by each pointer upon destruction?

The title is self explanatory - does the standard vector implementation take care of deallocating dynamic memory pointed to by all the pointers that are in the vector?
No. When you destroy a std::vector it destroys all its elements (calls their destructor) and then deallocates the storage used by the objects. But a (raw) pointer does not have a destructor - destroying it does not deallocate the object it points to - it just destroys the storage used to hold the pointer itself.
If you had had a vector of smart pointers (std::unique_ptr or std::shared_ptr) then it would be a different matter. Those classes do have destructors and do deallocate what they point to upon destruction (unique_ptr always, shared_ptr if it's the last object pointing to the contained object, otherwise it just decrements its reference count).
Note: a std::unique_ptr is a very thin wrapper around a raw pointer, that is designed to optimize away completely. So, using it should have zero overhead over a raw pointer when optimization is enabled. So it'll give you the semantics you want with no overhead compared to doing the manual memory management - manually.
No it doesn't.
If you want "self-deleting" pointers use smart pointers (std::unique_ptr or std::shared_ptr) or (depending on what the pointers are used for) a container such as std::vector, std::array or std::string.
No it doesn't. Containers are not reponsible of the memory management of raw pointers. It would be possible to automatically deallocate your pointer elements if they were smart pointers (RAII : https://fr.wikipedia.org/wiki/Resource_acquisition_is_initialization)
You can see a pointer as a simple integer. Its value represents a memory address. When the vector pointer element is deleted, the bytes allocated to store this address are freed. Thus, the memory address pointed by the pointer is lost (No more reference to it = memory leak).
Containers will never manipulate your instances (Free pointers, modify content). It can only call constructors (Specified one, copy, move...) and the destructor.
Depends on the what pointers the vector is containing, for raw pointers like
std::vector<Something*>
no, you have to do the cleanup yourself.
If the vector contains smart pointers, on the other hand, like std::unique_ptr
std::vector<std::unique_ptr<Something>>
then the cleanup is taken care of for you.
Long story short: try to use smart pointers.

Dynamic memory reallocation

If you allocate some space dynamically for example
struct node*py=new struct node;
struct node*tr=py;
delete py;
shouldn't the allocated memory still remain and not be freed since I do have another pointer pointing to the same address before the original pointer to the same is deleted?
No. That's simply not how memory allocation works in C++.
If you allocate memory with new, and then you call delete on it, it will get deleted. The memory manager has no facility for canceling or aborting a deletion once it's begun. C++ has a tendency of doing exactly what you ask it to do, so if you don't really want to free some memory, then don't call delete on it yet.
If you want reference counting, try using std::shared_ptr (or boost::shared_ptr, if you don't have the one in std yet).
no, the heap manager just does what it's told and frees the memory.
If you want to retain the memory based on how many references you have to the memory, then consider using reference-counted pointers such as C++11 shared_ptr (see, e.g., Dr Dobbs) or boost's smart pointers.
But you said it yourself - its only a pointer, therefore it doesnt know to what it points. it simply points to somewhere blindfolded.
No, in c/c++ the compiler/execution environment does not track refrences to memory, new and free mark memory as in use or not in use, and any refrence counting or other higher order garbage collection is left up to your program.

What do I have to garbage collect in a C++ destructor

I'm writing a C++ destructor (I hope that's the right term; I'm new to C++) and I'm not positive on what exactly I need to garbage collect. Let's say I have 2 pointers as instance variables do I need to garbage collect them? What about if I have an object as an instance variable? Or a pointer to an object?
I'm just a little fuzzy on what exactly needs to be deleted and what is automatically cleaned up.
Thanks
General rule of thumb is... if you called new, call delete. If you called new[], call delete[]. If you're accessing these pointers outside of the class and effectively sharing them, you'll want to be careful about the "owning" object deleteing the shared objects while they're still in use. Garbage collection isn't quite the right term. You want to destroy the object and free its memory. This is what delete/delete[] does. new/new[] allocate memory and construct an object.
In C++, there is no garbage collector. You must "manually" handle it. That's not to say that it's all tedium. You'll probably get into using smart pointers to handle some of this logic for you. See this question for more information.
You must delete every pointer you allocate with new. It's that simple, and it's that complicated; you must not lose track of any pointer allocated by new until you have deleted it.
Also, you need to make sure that if you use new[] to allocate a pointer, you call delete[] to deallocate it.
It's not about what pointers you happen to have in a class instance. You need to know who owns them (the owner is the one responsible for deleting them). If your object owns those pointers, then it should delete them. If it doesn't own them, then it shouldn't.
This is also why experienced C++ programmers avoid naked pointers where possible. Smart pointers allow you to express ownership types semantically in the language. That way, you don't have to keep track of who owns what; you know who owns it by the type of smart pointer being used.
You must call delete on every space you created using new, delete[] on every area created using new[], and free on everything you got using malloc.
You should also close any sockets you opened, and clear up any other OS resources your class owns.
Note: this is not called garbage collection. Garbage collection is when this process happens automatically, as part of a library or language runtime, not when you do it explicitly.
You should start by learning about "Resource Acquisition is Initialization" (RAII) and smart pointers (shared_ptr and unique_ptr). This is the idiom you have to know in C++ if you come from other languages.
Usual practice says that whatever you allocated in your constructor must be deallocated in your destructor (see other answers to know how). Event better, try to use values as much as possible and new as less as possible.
C++ loves the stack, and stack allocation and deallocation are automatic and cheap (no new, no delete). Use references and const-references instead of pointers.
If you really need dynamic memory, try to use one of the smart pointers.
Any memory you allocate using new operator needs to be freed.
You allocate memory by doing:
int * p1 = new int[5];
p2 = new int;
and you delete it by doing:
delete[] p1
delete p2;
If you are playing with Classes, you need to do the same thing in constructors (allocate) and destructors (deallocate).
In an ideal world, nothing. There are smart pointers and containers for every pattern. Sometimes, you will have to write your own, or augment existing implementations, but much of what you need exists already.
For an array, start with std::array and std::vector. For objects, read up on smart pointers and shared pointers. As a generalization: if you need to call delete, delete[] or free, you have usually headed down the wrong path.
You need to garbage collect all pointers that you don't no longer need. Otherwise you would have the dangling pointer problem.

Do I need to delete an static std::map?

In some classes I have an static std::map with pointers inside. My question is if I need to delete at the end of the program or this memory is automatically freed. My concern is if the pointers stored inside are correctly deleted through our destructors when std::map is deleted.
Thanks.
If the map contains pointers that were allocated with new (or new[], or malloc), then each pointer needs a corresponding delete (or delete[], or free).
The map's destructor wont know what to do with a bald pointer. Consider using a smart pointer that has appropriate move semantics like a boost smart pointer or if you've got a very new compiler, one of the C++0x smart pointers. However, do not use the current standard's std::auto_ptr, inside of STL containers. See this thread for why.
Edit:
As Billy ONeal pointed out, boost::ptr_map is also designed exactly for this purpose.
If I understand the situation correctly, you don't delete the map itself. But you probably need to delete the objects the map is pointing to. It would probably be a really good idea to use a smart pointer such as Boost shared_ptr in your map instead of native pointers. Then the objects would be cleaned up automatically.
Edit:
Using Boost ptr_map might be an even better idea.
The memory is "automatically freed", in the sense that the entire process memory is freed, but the destructors of the objects pointed to will not be called. This can cause a resource leak, if you use RAII.
std::map never calls delete on it's members. Assuming you're working with a relatively recent operating system, the OS will reclaim the memory occupied by the members on process termination, but the destructors will not run.
If you have a map of pointers, then the answer is 'no', your destructors will not be called, but 'yes', the memory will be freed at the end of process execution. All memory allocated by a process is always freed by the Operating System when a process exits (even if it crashes), but destructors might not be called.
A memory "leak" is where memory is unintentionally not deleted over a period of time, and ends up reducing as the process continues. If it is a type of process that runs for a very long period of time, eg a server that is rarely restarted, this can be a major problem.
Memory leak detectors will pick up on any memory that is allocated and not deleted by a programming call, so valgrind, etc. will report this as a leak.
It is as well to check your code with programs like valgrind, and therefore the less that "gets in the way", the easier it will be to spot real leaks. Therefore my advice is not do just let the system clean up the memory, or singletons, etc, for you when you have allocated a pointer with new (or malloc or new[]).
You can have a "clean-up" routine to do this. Just have an object in the scope of your map that has a deleter (as it will be deleted when it exits) that will clean up the pointers in the map. As you need your object to be deleted first it should be declared later than the map.
Like in any case of storage class which stores pointers: you are responsible to deallocate memory they point to. Storage class is responsible only to clean its own resources. Relying on reclaiming memory by OS at the process termination is a bad practice.

Delete pointer to a structure

one of the cpp files has a structure pointer created with "new" operator. Should that pointer be explicitly deleted? Or is the pointer automatically deleted?
C++ does not (normally) have automatic memory management. To free up the memory of that object you would use delete. When to use it is a different question.
EDIT: Also, the pointer will be deleted (or will be overwritten on the stack) when the function returns, but the object pointed at will stay in the heap until you delete it.
The use of the 'new' keyword will allocate memory on the heap, the same way 'malloc' does in C. To get that memory back when you're done using it, you have to do a 'delete' on the pointer returned from the 'new'.
This is easy when the life of some object does not extend outside the function where it was instantiated, but becomes more complicated when these objects are returned or added to collections...
As #Jared Updike notes, you have to do this by yourself. That's one reason why smart pointers such as those in Boost and C++0x are so widely used - they are lightweight classes that manage an underlying raw memory pointer, to avoid memory leaks when (not if) you forget to delete or delete[] raw pointers.
If you are new to C++ do yourself a favour and take a look at those (scoped_ptr, shared_ptr etc).
If you are looking for easier memory management, you may want to look at Shared Pointers . They are a convenient way to assure you that the memory will be freed if correclty used.