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 point to a dynamic array. Using a shared_ptr with dynamic arrays is possible when you give it a custom deleter, e. g. default_delete<T[]>
.
But I get a big error list as soon as I try to assign a new value to that field, even on construction.
Here's a minimal code sample:
#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;
// This line produces the error.
a.field = make_shared_array<char>(256);
return 0;
}
NB: Yes, I know that I could/should vector
instead of dynamic arrays. But their performance is not the same. I do some heavy image processing and the arrays hold the pixels. On less than VGA resolution the processing time increased from 8 to 11 s. That's quite a lot.
Update: Of course I can provide the errors here. I just didn't know if I should clutter the problem description with it. But here it is:
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\memory(754) : error C2664: 'std::_Ptr_base<_Ty>::_Reset0' : cannot convert parameter 1 from 'char ' to 'char ()[]'
with
[
_Ty=char []
]
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\memory(723) : see reference to function template instantiation 'void std::shared_ptr<_Ty>::_Resetp0<_Ux>(_Ux *,std::_Ref_count_base *)' being compiled
with
[
_Ty=char [],
_Ux=char
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\memory(723) : see reference to function template instantiation 'void std::shared_ptr<_Ty>::_Resetp0<_Ux>(_Ux *,std::_Ref_count_base *)' being compiled
with
[
_Ty=char [],
_Ux=char
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\memory(494) : see reference to function template instantiation 'void std::shared_ptr<_Ty>::_Resetp<_Ux,_Dx>(_Ux *,_Dx)' being compiled
with
[
_Ty=char [],
_Ux=char,
_Dx=std::default_delete
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\memory(494) : see reference to function template instantiation 'void std::shared_ptr<_Ty>::_Resetp<_Ux,_Dx>(_Ux *,_Dx)' being compiled
with
[
_Ty=char [],
_Ux=char,
_Dx=std::default_delete
]
problem.cpp(9) : see reference to function template instantiation 'std::shared_ptr<_Ty>::shared_ptr>(_Ux *,_Dx)' being compiled
with
[
_Ty=char [],
T=char,
_Ux=char,
_Dx=std::default_delete
]
problem.cpp(9) : see reference to function template instantiation 'std::shared_ptr<_Ty>::shared_ptr>(_Ux *,_Dx)' being compiled
with
[
_Ty=char [],
T=char,
_Ux=char,
_Dx=std::default_delete
]
problem.cpp(21) : see reference to function template instantiation 'std::shared_ptr<_Ty> make_shared_array(size_t)' being compiled
with
[
_Ty=char []
]
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.
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;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With