6

as of C++17 you can use make_unique in order to create smart pointers to arrays, such as:

unique_ptr<int[]> ptr = make_unique<int[]>(10);

which will create a smart pointer to an array of 10 elements (the fact that proper deleter[] will be called is also great).

However according to this make_shared does not support such functionality (at least not in C++17, to my understanding):

shared_ptr<int[]> ptr = make_shared<int[]>(10);

the code above is apparently illegal. Indeed, my Visual Studio 2017 (v141) spits out the following error:

C2070: 'int[]': illegal sizeof operand'

What's interesting is that shared_ptr itself does support array types (i.e., shared_ptr<int[]> is legal), but make_shared does not. Whereas make_unique does.

The question is, what prevented the standard maker people to let make_shared support array types, just like in the case of make_unique?

MutomboDikey
  • 155
  • 2
  • 12
  • 5
    `std::make_shared` supports arrays from C++20 https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared Why not earlier, I suppose because someone has to write the proposal, advocate for it, get 1 or more implementations written etc. They probably had something else scheduled. – Richard Critten Aug 30 '18 at 11:03
  • 5
    It was an oversight/deficiency in the c++14 and c++17 standards. It's in c++20. – Richard Hodges Aug 30 '18 at 11:03

1 Answers1

2

What prevented the standard maker people to let make_shared support array types [...]?

Probably nothing, this case was simply not considered, similar to std::make_unique not being present in C++11 but added in C++14. And as pointed out in the comments, this missing piece will ship with C++20.

There is a difference between std::unique_ptr and std::shared_ptr that made neglecting raw arrays pointers easy, though: custom deleters are part of std::unique_ptr's type but not part of std::shared_ptr's type. Therefore, you can handle an array like this

std::shared_ptr<int> array = std::shared_ptr<int>(new int[10],
    [](int *ptr){ delete []ptr; });

and hence delegate the correct memory cleanup to the point of object creation. This makes it easy to treat raw arrays as a special case of std::shared_ptr instances.

lubgr
  • 37,368
  • 3
  • 66
  • 117
  • 1
    It appears, however, that as of C++17 `shared_ptr ptr(new int[10])` similarly invokes delete[] (see the link in the original question). Also, I did not encounter any memory leaks when declaring a shared pointer in such fashion. Please correct me if I am wrong. – MutomboDikey Aug 30 '18 at 11:46
  • 1
    Seems that this is something libstdc++ provides, independent of the language standard (tested with `gcc-8` for `-std=c++11/14/17`), but not libc++ (tested with `clang-6`?! – lubgr Aug 30 '18 at 11:51
  • 4
    @lubgr IIRC and everything I see [here](https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr) shows me that `shared_ptr ptr(new int[10])` should work fine in C++17. Pre C++17 you could also use `std::unique_ptr arr(new int[1]); std::shared_ptr ptr(std::move(arr));` – NathanOliver Aug 30 '18 at 12:57
  • @NathanOliver You're right, I think I screwed up the flags for using the homebrew-up-to-date standard headers when testing. Should work with clang, too. – lubgr Aug 30 '18 at 13:13