Why isn't there a std::shared_ptr<T[]> specialisation?
Asked Answered
M

1

67

The standard provides a template specialization of std::unique_ptr which correctly calls the delete[] from its destructor:

void func()
{
   std::unique_ptr< int[] > arr(new int[10]);

   .......
}

With std::shared_ptr this specialisation is not available, so it is necessary to to provide a deleter which correctly calls delete[]:

void func()
{
    // Usage
    shared_ptr array (new double [256], [](double* arr) { delete [] arr; } ); 

    ..............
}

Is this simply an oversight? (in the same way that there is an std::copy_if) or is there a reason?

Manna answered 20/1, 2012 at 20:38 Comment(2)
N.B. there's a new proposal to add this for C++17, based on work in Boost, see open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3640.htmlSe
Notice that a lot of the shared_ptr machinery should be disabled when working with arrays, such as the ability to refer to a subobject.Saltation
G
72

The LWG (Library Working Group of the C++ committee) briefly considered the possibility but the idea wasn't without controversy. Though the controversy was mainly about a feature added to the shared_ptr<T[]> proposal that could have been jettisoned (arithmetic on shared_ptr<T[]>).

But ultimately the real real reason is that though it was discussed, there was never an actual written proposal in front of the LWG to do this. It never bubbled up anyone's priority list (including my own) sufficiently to put the time into writing a proposal.

Informal conversations have recently begun anew on this topic among a few LWG members, and I have personally prototyped it. But there is still no written proposal for it. I think it would be a decent additional tool in the toolbox. Whether it will ever actually happen or not is anyone's guess.

Update

Array support for shared_ptr now has a draft TS:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4077.html

Update (2017)

This is now supported in C++17. See case 3 of shared_ptr::shared_ptr()

Gamble answered 20/1, 2012 at 20:49 Comment(9)
First "why isn't there..." question with a real answer that I've seen, also, a dynamically allocated array? With vector and std::array, really don't see the need(?)Vizcacha
@Nim: std::unique_ptr<T[]> (which exists) is good for when overhead is tremendously important to you. Unlike vector<T>, unique_ptr<T[]> does not include overhead for capacity, or even size. The client will probably need to add external overhead for size, but if the array is never resized, not for capacity. Now this doesn't make unique_ptr<T[]> a better vector<T>. Indeed, I think the use cases of the former will be rare compared to the latter. But the use case rate isn't zero for the former.Gamble
Analogously, shared_ptr<T[]> can sometimes replace shared_ptr<vector<T>> with lower overhead. The mere existence and continued support of boost::shared_array<T> is an argument that some programmers find such a tool occasionally useful.Gamble
Trivia: The unique_ptr<T[]> syntax was born in 2001 on comp.lang.c++ by this interesting question about auto_ptr: groups.google.com/group/comp.lang.c++/browse_thread/thread/…Gamble
@HowardHinnant: I don't see the advantage of shared_ptr<T[]>(new T[99]) over make_shared<vector<T>>(99). In both cases we can expect two allocations and the overhead needed to make vector self-aware about its capacity and size is probably negligible.Campuzano
@sellibitze: The benefit of the shared_ptr<T[]> version is that it only requires one pointer dereference to get to any of the array elements, while shared_ptr<vector<T>> requires two (one for the shared_ptr, one for the array stored in the vector).Dietary
@JeremiahWillcock: Point taken. But I suppose it's possible to save this first dereference operation (at least for most element accesses) by using iterators during a loop or something like this.Campuzano
Consider a serial port class that calls a functor when a complete message is read but the size differs from message to message. Since you read the data as a byte array, it would be more convenient to transfer the data as shared_ptr<unsigned char*> than anything else.Wearproof
Is there a reason, why everyone seems to ignore shared_ptr<std::array<T,N>>? Is there any downside compared to shared_ptr<T[]> that I overloked?Scutt

© 2022 - 2024 — McMap. All rights reserved.