I read in a few articles that raw pointers should almost never be used. Instead they should always be wrapped inside smart pointers, whether it's scoped or shared pointers.
However, I noticed that frameworks like Qt, wxWidgets and libraries like Boost never return nor expect smart pointers, as if they were not using them at all. Instead, they return or expect raw pointers. Is there any reason for that? Should I stay away from smart pointers when I write a public API, and why?
Just wondering why smart pointers are recommended when many major projects seem to avoid them.
unique_ptr
? None whatsoever. Are Qt/WxWidgets targetted at embedded or real time systems? No, they're intended for Windows/Mac/Unix on a desktop- at most. Smart pointers are for programmers who want to get it correct.
Apart from the fact that many libraries were written before the advent of standard smart pointers, the biggest reason is probably the lack of a standard C++ Application Binary Interface (ABI).
If you’re writing a header-only library, you can pass around smart pointers and standard containers to your heart’s content. Their source is available to your library at compile time, so you rely on the stability of their interfaces alone, not of their implementations.
But because of the lack of standard ABI, you generally cannot pass these objects safely across module boundaries. A GCC shared_ptr
is probably different from an MSVC shared_ptr
, which too can differ from an Intel shared_ptr
. Even with the same compiler, these classes are not guaranteed to be binary compatible between versions.
The bottom line is that if you want to distribute a prebuilt version of your library, you need a standard ABI on which to rely. C doesn’t have one, but compiler vendors are very good about interoperability between C libraries for a given platform—there are de facto standards.
The situation is not as good for C++. Individual compilers can handle interoperation between their own binaries, so you have the option of distributing a version for every supported compiler, often GCC and MSVC. But in light of this, most libraries just export a C interface—and that means raw pointers.
Non-library code should, however, generally prefer smart pointers over raw.
There can be many reasons. To list few of them:
Smart pointers became part of standard just recently. Till then they were part of other libraries Their primary use is to avoid memory leaks; many libraries don't have their own memory management; Generally they provide utilities and APIs They are implemented as wrapper, since they are actually objects and not pointers. Which has additional time/space cost, compared to raw pointers; The users of the libraries may not want to have such overheads
Edit: Using smart pointers is a completely developer's choice. It depends on various factors.
In performance critical systems, you may not want to use smart pointers which generates overhead The project which needs the backward compatibility, you may not want to use the smart pointers which has C++11 specific features
Edit2 There is a string of several downvotes in the span of 24 hours because of below passage. I fail to understand why the answer is downvoted even though below is just an add-on suggestion and not an answer. However, C++ always facilitates you to have the options open. :) e.g.
template<typename T>
struct Pointer {
#ifdef <Cpp11>
typedef std::unique_ptr<T> type;
#else
typedef T* type;
#endif
};
And in your code use it as:
Pointer<int>::type p;
For those who say that a smart pointer and a raw pointer are different, I agree with that. The code above was just an idea where one can write a code which is interchangeable just with a #define
, this is not compulsion;
For example, T*
has to be deleted explicitly but a smart pointer does not. We can have a templated Destroy()
to handle that.
template<typename T>
void Destroy (T* p)
{
delete p;
}
template<typename T>
void Destroy (std::unique_ptr<T> p)
{
// do nothing
}
and use it as:
Destroy(p);
In the same way, for a raw pointer we can copy it directly and for smart pointer we can use special operation.
Pointer<X>::type p = new X;
Pointer<X>::type p2(Assign(p));
Where Assign()
is as:
template<typename T>
T* Assign (T *p)
{
return p;
}
template<typename T>
... Assign (SmartPointer<T> &p)
{
// use move sematics or whateve appropriate
}
std::auto_ptr
that has been part of the standard for a long time (and note, I do like std::auto_ptr
as the return type for functions creating objects, even if it is almost useless everywhere else). In C++11 std::unique_ptr
has no additional costs over a plain pointer.
unique_ptr
and disappearance of auto_ptr
, code targeting C++03 should use the later, while code targeting C++11 can use the former. Smart pointers are not shared_ptr
, there are many standard and none standard, including proposals to the standard that were rejected as managed_ptr
unique_ptr
incur runtime cost, but unique_ptr
is by far the one that is most commonly used. The code sample you provide is also misleading, because unique_ptr
and T*
are entirely different concepts. The fact that you refer to both of them as type
gives the impression that they can be swapped out for one another.
There are two issues with smart pointers (pre C++11):
non-standards, so each library tend to reinvent its own (NIH syndrom & dependencies issues)
potential cost
The default smart pointer, in that it is cost-free, is unique_ptr
. Unfortunately it requires C++11 move semantics, which only appeared recently. All other smart pointers have a cost (shared_ptr
, intrusive_ptr
) or have less than ideal semantics (auto_ptr
).
With C++11 around the corner, bringing a std::unique_ptr
, one would be tempted to think that it is finally over... I am not so optimistic.
Only a few major compilers implement most of C++11, and only in their recent versions. We can expect major libraries such as QT and Boost to be willing to retain compatibility with C++03 for a while, which somewhat precludes the wide adoption of the new and shiny smart pointers.
You shouldn't stay away from smart pointers, they have their use especially in applications where you have to pass a object around.
Libraries tend to either just return a value or populate a object. They don't usually have objects that need to be used in a lot of places, so there is no need for them to use smart pointers (at least not in their interface, they may use them internally).
I could take as example a library we have been working on, where after a few months of development I realized we only used pointers and smart pointers in a few classes (3-5% of all classes).
Passing variables by reference was enough in most places, we used smart pointers whenever we had a object that could be null, and raw pointers when a library that we used forced us to.
Edit (I can't comment because of my reputation): passing variables by reference is very flexible: if you want the object to be readonly you can use a const reference (you can still do some nasty casts to be able to write the object) but you get the maximum of protection possible (it's the same with smart pointers). But I do agree that it's much nicer to just return the object.
Qt pointlessly re-invented many parts of the Standard library in an attempt to become Java. I believe that it does actually have its own smart pointers now, but in general, it is hardly a pinnacle of design. wxWidgets, as far as I'm aware, was designed long before usable smart pointers were written.
As for Boost, I fully expect that they use smart pointers wherever appropriate. You might have to be more specific.
In addition, don't forget that smart pointers exist to enforce ownership. If the API has no ownership semantics, then why use a smart pointer?
QString
, wxWidgets has wxString
, MFC has the horribly named CString
. Isn't a UTF-8 std::string
good enough for 99% of GUI tasks?
Good question. I don't know the specific articles to which you refer, but I have read similar things from time to time. My suspicion is that the writers of such articles tend to harbor a bias against C++-style programming. If the writer programs in C++ only when he must, then returns to Java or such as soon as he can, then he doesn't really share the C++ mindset.
One suspects that some or most of the same writers prefer garbage-collecting memory managers. I don't, but I think differently than they do.
Smart pointers are great, but they have to keep reference counts. The keeping of reference counts bears costs -- often modest costs, but costs nonetheless -- at runtime. There is nothing wrong with saving these costs by using bare pointers, especially if the pointers are managed by destructors.
One of the excellent things about C++ is its support for embedded-systems programming. The use of bare pointers is part of that.
Update: A commenter has correctly observed that C++'s new unique_ptr
(available since TR1) does not count references. The commenter also has a different definition of "smart pointer" than I have in mind. He may be right about the definition.
Further update: The comment thread below is illuminating. All of it is recommended reading.
shared_ptr
keeps a reference count. There are many other smart pointer types which do not keep a reference count at all. Finally, the libraries mentioned are targetted at platforms which have plenty of resources to spare. Not that I was the downvoter, but all I'm saying is that your post is full of wrong.
shared_ptr
has no overhead. It only has overhead if you don't need thread-safe shared ownership semantics, which is what it provides.
There are also other types of smart pointers. You might want a specialized smart pointer for something like network replication (one that detects if it's accessed and sends any modifications to the server or some such), keeps a history of changes, marks the fact that it was accessed so it can be investigated when you save data to disk and so on. Not sure if doing that in the pointer is the best solution but using the built in smart pointer types in libraries could result in people being locked into them and loosing the flexibility.
People can have all kinds of different memory management requirements and solutions beyond smart pointers. I might want to manage memory myself, I could be allocating space for things in a memory pool so it's allocated in advance and not at runtime (useful for games). I might be using a garbage collected implementation of C++ (C++11 makes this possible although none exist yet). Or maybe I'm just not doing anything advanced enough to worry about bothering with them, I can know that I'm not going to forget to uninitialized objects and so on. Maybe I'm just confident in my ability to manage memory without the pointer crutch.
Integration with C is another issue too.
Another issue is smart pointers are part of the STL. C++ is designed to be usable without the STL.
It also depends on what domain you work in. I write game engines for a living, we avoid boost like the plague, in games the overhead of boost isn't acceptable. In our core engine we ended up writing our own version of stl (Much like the ea stl).
If i was to write a forms application, i might consider using smart pointers; but once memory management is second nature not having granular control over memory becomes quiet annoying.
Success story sharing