Here\'s a notable video (Stop teaching C) about that paradigm change to take in teaching the c++ language.
And an also notable blog post
There is still a chance to use malloc/free
in C++, as you can use new/delete
, and anything higher level wrapping the STL
memory templates provided.
I think in order to really learn C++ and especially understand the C++11 memory templates you should create simple structures with new
and delete
. Just to better understand how they work. All the smart pointer classes rely on those mechanisms. So if you understand what new
and delete
does, you are going to appreciate the template more and really find smart ways to use them.
Today I personally try to avoid them as much as possible, but one main reason is the performance, which you should care if it is critical.
These are my rules of thumb I always have in mind:
std::shared_ptr
: Automatic management of pointers but due to the reference counting it uses for tracing the accessed pointers, you have a worse performance every time you access these objects. Compared simple pointers I would say 6 times slower. Keep in mind, you can use get()
and extract the primitive pointer, and continue accessing it. Of you must be careful with that one. I like to as that as a reference with *get()
, so the worse performance is not really a deal.
std::unique_ptr
The pointer access may only happen at one point in the code. Because this template forbids copy, thanks to the r-references &&
feature, it is much faster than an std::shared_ptr
. Because there is still some ownership overhead in this class I would say, they are about twice as slow as a primitive pointer. You access the object than the primitive pointer within that template. I also like to use reference trick here, for less required accesses to the object.
About performance, it might be true, that those templates are slower, but keep in mind that if you want to optimize software, you should profile first and see what really takes many instructions. It is very unlikely that smart-pointers are the problem, but sure it depends on your implementation.
In C++ no one should care about malloc
and free
, but they exist for legacy code. They differ basically in the fact, that they know nothing about c++ classes, which with new
and delete
operator case is different.
I use std::unique_ptr
and std::shared_ptr
in my project Commander Genius everywhere and I'm really happy that they exist. I have not to deal with memory leaks and segfaults since then. Before that, we had our own smart-pointer template. So for productive software, I cannot recommend them enough.
Adding to other answers, there are some cases where new/delete make sense -
When ownership should not be local.
As an example, a pointer container may not want ownership over the pointers in it to reside in the pointers themselves. If you try to write a linked list with forward unique ptrs, at destruction time you can easily blow the stack.
A vector
-like container of owning pointers may be better suited to storing delete operation at the container or subcontainer level, and not at the element level.
In those and similar cases, you wrap ownership like a smart pointer does, but you do it at a higher level. Many data structures (graphs, etc) may have similar issues, where ownership properly resides at a higher point than where the pointers are, and they may not map directly to an existing container concept.
In some cases it may be easy to factor out the container-ownership from the rest of the data structure. In others it may not.
Sometimes you have insanely complex non-local non-reference counted lifetimes. There is no sane spot to put the ownership pointer in those cases.
Determining correctness here is hard, but not impossible. Programs that are correct and have such complex ownership semantics exist.
All of these are corner cases, and few programmers should run into them more than a handful of times in a career.
For simple use cases, smart pointers, standard containers and references should be enough to use no pointers and raw allocation and de-allocation.
Now for the cases I can think about:
Another use case may be 3rd party library returning raw pointer which is internally covered by own intrusive reference counting (or own memory management - which is not covered by any API/user interface).
Good example is OpenSceneGraph and their implementation of osg::ref_ptr container and osg::Referenced base class.
Although it may be possible to use shared_ptr, the intrusive reference counting is way better for scene graph like use cases.
Personally I do see anything "smart" on the unique_ptr. It is just scope locked new & delete. Although shared_ptr looks way better, it requires overhead which is in many practical cases unacceptable.
So in general my use case is:
When dealing with non-STL raw pointer wrappers.
The OP specificly asks about how/when handrolling will be more efficient in an everyday use case - and I will address that.
Assuming a modern day compiler/stl/platform, there is not an every day use where handrolled use of new and delete will be more efficient. For the shared_ptr case i believe it will be marginal. In an extremely tight loop(s) there could be something to gain by just using raw new to avoid the ref counting (and find some other method of cleaning up - unless somehow imposed on you, you choose to use shared_ptr for a reason), but that is not an everyday or common example. For the unique_ptr there is not actually any difference, so i think it is safe to say that it is more of rumour and folklore and that performance wise it will not actually matter at all (difference will not be measurable in normal cases).
There are cases where it is not desirable or possible to use a smart pointer class as already covered by others.