Why do C++ libraries and frameworks never use smart pointers?

C++PointersSmart Pointers

C++ Problem Overview


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.

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

There can be many reasons. To list few of them:

  1. Smart pointers became part of standard just recently. Till then they were part of other libraries
  2. Their primary use is to avoid memory leaks; many libraries don't have their own memory management; Generally they provide utilities and APIs
  3. 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.

  1. In performance critical systems, you may not want to use smart pointers which generates overhead

  2. 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
}

Solution 3 - C++

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.

Solution 4 - C++

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.

Solution 5 - C++

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?

Solution 6 - C++

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.

Solution 7 - C++

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.

Solution 8 - C++

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionlaurentView Question on Stackoverflow
Solution 1 - C++Jon PurdyView Answer on Stackoverflow
Solution 2 - C++iammilindView Answer on Stackoverflow
Solution 3 - C++Matthieu M.View Answer on Stackoverflow
Solution 4 - C++Robot MessView Answer on Stackoverflow
Solution 5 - C++PuppyView Answer on Stackoverflow
Solution 6 - C++thbView Answer on Stackoverflow
Solution 7 - C++David C. BishopView Answer on Stackoverflow
Solution 8 - C++Ugly DavisView Answer on Stackoverflow