Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 880
laurent Avatar asked Apr 26 '12 13:04

laurent


People also ask

What problem does using smart pointers help prevent?

Smart pointers try to prevent memory leaks by making the resource deallocation automatic: when the pointer to an object (or the last in a series of pointers) is destroyed, for example because it goes out of scope, the pointed object is destroyed too.

Why do we need smart pointers in C++?

In modern C++ programming, the Standard Library includes smart pointers, which are used to help ensure that programs are free of memory and resource leaks and are exception-safe.

Why the usage of pointers in C++ is not recommended?

It is best to avoid using pointers in C++ as much as possible. The use of pointers can lead to confusion of ownership which can directly or indirectly lead to memory leaks. Even if object ownership is well managed simple (and difficult to find) bugs can also lead to memory leaks.


2 Answers

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.

like image 113
Jon Purdy Avatar answered Oct 17 '22 04:10

Jon Purdy


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
}
like image 39
iammilind Avatar answered Oct 17 '22 04:10

iammilind