I am having this problem that I often use a vector of pointers to some objects.
The problem is that I need to delete pointers in that vector manually which is prone to errors / memory leaks.
Currently I am doing it like this:
1 2 3 4 5 6 7 8 9 10
typedef std::vector<MyObject*> TMyObjects;
void deleteVectors(TMyObjects &MyObjects)
{
for (auto i = MyObjects.begin(); i != MyObjects.end(); ++i)
{
delete((*i));
}
MyObjects.clear();
}
So I would like to get rid of using deleteVectors. I've found two solutions to this problem:
1. I could use Boost library which has pointer containers created for this purpose.
2. I could create a custom allocator which I pass when creating the instance of vector.
I don't want to use the Boost library so I am left up with the solution number 2. The thing is, that my C++ knowledge is yet not good enough to write such allocator by myself. Could someone help me or point me to a code snippet that perfrom this task?
> how about the solution based on custom allocator?
A standard allocator-aware container would use its allocator for managing storage for the values it holds.
std::vector< MyObject*, my_custom_allocator > would use the allocator to manage storage for holding pointers to MyObject, not for the MyObject instances that these pointers point to.
To illustrate,
1 2 3 4 5 6 7 8 9
std::vector< MyObject*, my_custom_allocator > my_vector ;
my_vector.push_back(nullptr) ;
my_vector.push_back(nullptr) ;
static MyObject my_first_object( /* ... */ ) ;
my_vector[0] = std::addressof(my_first_object) ; // the allocator does not get to know about this
my_vector[1] = new MyObject( /* ... */ ) ; // the allocator does not get to know about this
> am I wrong thinking that my_custom_allocator is able to call the destructor for the dereferenced pointer?
It won't be able to do that (with a dumb pointer) consistently and correctly.
For instance, consider:
1 2 3 4 5 6 7 8 9 10
void foo( std::vector< MyObject*, my_custom_allocator > arg ) // passed by value
{
// ...
// arg is destroyed when the function returns; the destructor would ask the allocator to
// destroy the pointers and deallocate the memory
}
std::vector< MyObject*, my_custom_allocator > my_vector ;
my_vector.push_back( new MyObject( /* ... */ ) ;
foo( my_vector ) ; // pass a copy of my_vector
I think I understand now. So I've tried to use your suggestion with container of smart pointers but I am having problem when I try to pass object to the vector by initializer list.
Could you explain me the reason of the error and how to fix it?
Is this because initializer list is creating a temporary vector which then is passed to lMyObjects and it tries to copy elements of this vector which are unique pointers that can't be copied?
std::initializer_list<T> is a proxy for an array of objects.
The vector needs to copy the objects from the underlying array, and std::unique_ptr<> is not copyable (deleted copy constructor)
Something like this perhaps:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
class TMyObject
{
public:
TMyObject(int ID) : id(ID) {};
int id;
TMyObject(TMyObject&& o) {};
TMyObject(const TMyObject&) = delete;
TMyObject& operator=(const TMyObject&) = delete;
};
int main()
{
std::vector< std::unique_ptr<TMyObject> > my_objects ;
my_objects.push_back( std::make_unique<TMyObject>(1) ) ; // move constructed into the vector
my_objects.push_back( std::unique_ptr<TMyObject>( new TMyObject(2) ) ) ; // clumsy, avoid
// use std::make_unique instead
}