I wanted to replace some raw pointers in my class with a std::shared_ptr
so that I don\'t have to worry when I create copies of that class. But the raw pointers
If you insist that you should not use std::vector
, Boost has a boost::shared_array that works as a smart pointer to manage a dynamically allocated array of object.
shared_ptr
is not designed to handle an array. Since shared_array
is available, why try to use shared_ptr
on array s?
If you specified the deleter then you don't use T[]
in the template argument. Just change T[]
to T
:
template <typename T> shared_ptr<T> make_shared_array(size_t size)
{
return shared_ptr<T>(new T[size], default_delete<T[]>());
}
struct Foo
{
shared_ptr<char> field;
};
std::unique_ptr
is specialized for array types so you can use T[]
with it and it will know that it's still just storing a T*
. std::shared_ptr
is not specialized this way and so a shared_ptr<T[]>
will try to store a pointer to an array, T(*)[]
, which won't work very well with the conventions around raw arrays in C++. Not to mention that an array of unknown size is an incomplete type, and shared_ptr
will eventually need a complete type.
You mention knowing that std::vector
should be a better solution but doesn't perform as well. It should perform just fine and you'd probably be better off figuring out why it doesn't.
The solution you suggest is possible, but you will lose the size of the array:
#include <memory>
#include <cstddef>
using namespace std;
template<typename T> shared_ptr<T> make_shared_array(size_t size)
{
return shared_ptr<T>(new T[size], default_delete<T[]>());
}
struct Foo
{
shared_ptr<char> field;
};
int main()
{
Foo a;
a.field = make_shared_array<char>(256);
return 0;
}
What I have done here is to let the array decay into a pointer. As long as the deleter is an array deleter it should behave correctly.
To prevent this loss of size, and if you cannot use boost::shared_array as suggested, I would suggest to encapsulate this information in your own shared_array class.