2

Scott Meyers mentions in his book, Effective Modern C++, that using shared_ptr to arrays is discouraged because when converted to Base class pointers it creates "holes" in the type system.

However, it is possible to create shared_ptr<T> from unique_ptr<T[]> in the following way

std::shared_ptr<D> pDerived = std::shared_ptr<D>(std::make_unique<D[]>(3)); // Create an array of 3 D's

Is the above code potentially dangerous? Are there pitfalls if pDerived is later copied into a pBase?

std::shared_ptr<B> pBase = pDerived; // B is the base class for D
tcb
  • 4,408
  • 5
  • 34
  • 51
  • Re-opened because http://stackoverflow.com/q/30495941/981959 only talks about the first question, not upcasting to `shared_ptr` – Jonathan Wakely Sep 09 '15 at 15:26

1 Answers1

5

Is the above code potentially dangerous?

It depends what you do with it.

It won't leak resources because the default_delete<D[]> that uses delete[] will be copied from the unique_ptr and stored in the shared_ptr (as described at Initialization of shared_ptr<T> from unique_ptr<T[]>).

Are there pitfalls if pDerived is later copied into a pBase?

Yes, if you do something like pBase.get()[1] then that is not a valid pointer to the second element if sizeof(B) != sizeof(D)

std::experimental::shared_ptr from the Library Fundamentals TS supports arrays properly (as proposed by N3939).

With the version in the TS, shared_ptr<D> does not allow construction from a unique_ptr<D[]>, but shared_ptr<D[]> does. A shared_ptr<D[]> cannot be converted to shared_ptr<B[]>, to avoid the safety problem you refer to.

The support for arrays might make it into std::shared_ptr in a future C++ standard, but is only in the TS for now.

Community
  • 1
  • 1
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521