I have this:
std::vector <BinaryTree*> children;
where BinaryTree is a class. How can I add an element into this vector?
I tried children.push_back(X) where X is an instance of the class but it gives me this error:
cannot convert parameter 1 from 'BinaryTree' to 'BinaryTree *&&'
Just use the push_back() and pass a pointer to an instance of BinaryTree:
std::vector <BinaryTree*> children;
BinaryTree* pTree = new BinaryTree();
children.push_back(pTree);
...
delete pTree;
In order to avoid manual memory management, if you need reference semantics, use smart pointers instead of raw pointers:
#include <memory> // For std::shared_ptr
std::vector <std::shared_ptr<BinaryTree>> children;
std::shared_ptr<BinaryTree> pTree = std::make_shared<BinaryTree>();
children.push_back(pTree);
...
// No need to delete pTree
The std::shared_ptr<> class template is part of the C++11 Standard Library. In C++03, you could use the (almost) equivalent boost::shared_ptr<>:
#include <boost/shared_ptr.hpp> // For std::shared_ptr
std::vector <boost::shared_ptr<BinaryTree>> children;
boost::shared_ptr<BinaryTree> pTree = boost::make_shared<BinaryTree>();
children.push_back(pTree);
...
// No need to delete pTree
Finally, if you do not need reference semantics at all and want to treat your binary trees as values instead, you can even consider defining a std::vector<BinaryTree>:
std::vector<BinaryTree> children;
BinaryTree tree;
children.push_back(tree);
Omit the asterisk * from the template argument:
std::vector<BinaryTree> children;
You want children to hold the data, without manual/dynamic memory allocation as in new BinaryTree.
It really depends on who is supposed to own the pointers. In the simplest case, where the vector doesn't own them, then you pass the address of a BinaryTree object.
BinaryTree b = ...;
children.push_back(&b);
But you have to be sure b lives at least as long as children does.
If the vector owns the pointers, then you should probably store smart pointers to avoid having to deal with memory managemen:
std::vector<std::unique_ptr<BinaryTree>> children;
children.push_back(std::unique_ptr<BinaryTree>(new BinaryTree(args)));
If you don't know what all this "ownership" business means, then you are most likely better off with a plain vector of objects:
std::vector<BinaryTree> children;
std::vector<SomeObject*> objectVector;
objectVector.push_back(new SomeObject());
Is how I do it.
children.push_back(&X);
This will work but bear in mind that once your object leaves scope, its deleter will be called and you will be left with an invalid pointer.
children.push_back(&X);
Pass the address as if you were using it as a pointer. But the problem then is if that instance goes out of scope, so better to do this
BinaryTree* X = new BinaryTree;
children.push_back(X);
This will ensure that X never goes out of scope, but then you have to manually delete it when you're finished with it.
The vector contains pointers to objects of type BinaryTree. You need
BinaryTree bt;
children.push_back( &bt );
But you must ensure that the lifetime of the bt object at least matches that of the vector.
You may want this instead
children.push_back( new BinaryTree );
But in this case you must call delete on the pointer contained in the vector to prevent a memory leak.
As evident, neither option is easy to manage. An easy change is to make your container store the elements by value.
std::vector<BinaryTree> children;
BinaryTree bt;
children.push_back( bt );
If you must store pointers, use a smart pointer to hold them instead.
std::vector<std::unique_ptr<BinaryTree>> children;
children.push_back( new BinaryTree );
Now you don't need to worry about deleting the objects before emptying the vector.
You have vector of pointers:
std::vector <BinaryTree*> children;
so the proper way of adding elements is:
BinaryTree* child = new BinaryTree();
children.push_back(child);
just be careful while doing something like this:
{
BinaryTree child;
children.push_back(&child);
}
because lifetime of such an element might be shorter than lifetime of the vector and you might end up trying to access an element that no longer exists (dangling pointer) which produces undefined behavior. Also don't forget to delete these elements when done with it.
But it's always good to consider using vector of objects first (i.e.std::vector<BinaryTree>) since that would take care of that ugly memory management for you.
Related
So I essentially want to do this:
struct A {
A *children[10];
};
However, when I do this and create a destructor such as:
virtual ~A() {
for (A *child: children) {
delete child;
}
}
I get a segmentation fault and I'm not sure why. So how can I accomplish holding a list of A within A using an STL class so I don't have to worry about new/delete? I tried vector and get an "incomplete type" error.
So
In for (A *child: A) { delete child; ... you should probably be iterating over children, not A.
For the above to work, you should store your children in a std::vector, not a raw array (std::vector<A> children).
Use a smart pointer of your choice (like std::shared_ptr) instead of raw pointers, then you don't have to delete anything.
This:
for (shared_ptr<A> child: a.get()->children) {
does not iterate over children -- it iterates over copies of the pointers in children. So in each iteration, you make a copy of the (null) shared pointer (child) then set that loop-local copy to a newly allocated object, then child goes out of scope and the allocated object is freed. The pointers in the children array are never modified.
What you want is:
for (shared_ptr<A> &child: a.get()->children) {
the explicit reference (&) means that in each iteration of the loop, child will be a reference to the shared_ptr in the children array rather than a copy. So when you assign to it, it will modify the array.
I would like to know if I should manually release the memory reserved by std::vector and its elements in the destructor of the class that contains that vector. And if so - how exactly?
Situation #1 - std::vector of primitive types:
class A{
std::vector<int> elements;
A(){...}
};
Situation #2 - std::vector of complex types:
class B{
int b;
C * pointer;
...
};
class A{
std::vector<B> elements;
A(){...}
};
Situation #3 - std::vector of pointers to complex types:
class B{
int b;
C * pointer;
...
};
class A{
std::vector<B*> elements;
A(){...}
};
In which cases the destructor of A should be empty? In which it should look like:
A::~A(){
for(auto &e : elements){
delete e;
}
elements.clear();
}
I think about situation, when elements belongs only to A and are not shared by any other structure (when A is destroyed, the elements should also be destroyed).
It seems obvious that for std::vector of pointers, I have to use delete e on each element.
But:
Do I really have to call elements.clear(); (the object will be destroyed after that line - isn't it waste of instructions)?
Maybe I should also use erase(...) method of std::vector in loop? If so, wouldn't clear() make all the work for me instead (when the std::vector does not contains pointers)?
Did I miss something? What's the best approach?
p.s. Situation #3 is about pointers and not a shared pointers.
I would like to know if I should manually release the memory reserved by std::vector and its elements in the destructor of the class that contains that vector.
No, you never need to do that. Like any well designed RAII type, standard containers automatically destroy their contained objects when they are erased from the container (which includes erasing all the elements by destroying the container).
It seems obvious that for std::vector of pointers, I have to use delete e on each element.
Only if you're abusing the pointers to imply ownership of the objects they point to. We have smart pointers to make the ownership explicit, and automatically delete the objects at the right time.
Do I really have to call elements.clear();
No, the destructor will take care of that.
Maybe I should also use erase(...) method of std::vector in loop?
No, that would be even worse. It would invalidate the iterator used by the loop, giving undefined behaviour. The destructor will erase all the elements for you.
What's the best approach?
Store objects when you can. If you need pointers, store smart pointers if you want the container to "own" the objects, or regular pointers (or perhaps weak pointers) if you're managing the objects in some other way and just want the container to refer to them.
I have had a good look at some other questions on this topic and none of them (to my knowledge) address how to correctly erase items from a stl list of objects which contain dynamicically assigned memory vs. a stl list of objects that don't contain dynamically assigned memory.
I want to use a list of objects. Take this object for example (which contains no dynamically assigned memory):
class MyPoint {
public:
MyPoint(int _x,int _y)
{
x = _x;
y = _y;
}
private:
int x;
int y;
};
So I might create a list of objects (not pointers to them), add things to it and then erase an element:
list<MyPoint> myList;
myList.push_back(MyPoint(3,4));
myList.push_back(MyPoint(1,2));
myList.push_back(MyPoint(8,8));
myList.push_back(MyPoint(-1,2));
list<MyPoint>::iterator it;
it = myList.begin();
advance(it,2);
myList.erase(it);
My list now contains:
(3, 4)
(1, 2)
(-1, 2)
QUESTION 1a: do I need to do anything else to the erased object or will the memory be taken care of?
QUESTION 1b: if the program ends, do I need to do something with the remaining objects in the list? Do I need to delete them all and deal with their memory somehow?
Ok, now consider an alternative version of the class that allowed a point in N-dimensional space. I.e., I could dynamically assign an array of length N to hold the N points inside the class (I have spared you the implementation as that is not in question here). The destructor of the class would then delete the dynamically assigned array using 'delete'.
class MyDynamicPoint {
public:
MyDynamicPoint(int N)
{
points = new int[N];
}
~MyDynamicPoint()
{
delete points;
points = NULL;
}
private:
int *points;
};
I might now create a list of pointers to the objects, instead of the objects themselves:
list<MyDynamicPoint*> myList;
myList.push_back(new MyDynamicPoint(8));
myList.push_back(new MyDynamicPoint(10));
myList.push_back(new MyDynamicPoint(2));
myList.push_back(new MyDynamicPoint(50));
list<MyDynamicPoint*>::iterator it;
it = myList.begin();
advance(it,2);
myList.erase(it);
QUESTION 2a - Is the above correct? I.e. Because this new version of the class would contain some dynamically assigned memory, does this mean I have to create a list of pointers to objects, not the objects themselves?
QUESTION 2b - Given that I have just erased the pointer from the list, where do I call delete to deal with the fact there is now dynamic memory to be deleted in the objects? Or does the erase method of stl list call the destructor of the object, taking care of it?
Many thanks in advance for any help,
Best,
Adam
When you have a class with data members that have automatic storage duration (i.e. their lifetime is tied to the instance of this class) like this:
class MyPoint {
private:
int x;
int y;
};
and you will use list<MyPoint> myList;, then this instance of std::list is also an object with automatic storage duration, that will be cleaned up automatically and by the time the container is destructed, so are the elements it holds. Everything is taken care of.
But the latter version is not very lucky choice... not only that you have a container holding pointers, you even decided to create a data member of class Point that will be allocated dynamically. At first note that everything that has been allocated by calling new should be freed by calling delete and everything allocating by calling new[] should be freed by calling delete[].
In this situation, you are allocating the memory when the object is constructed and cleaning it up when the object is destructed:
MyDynamicPoint(int N)
{
points = new int[N];
}
~MyDynamicPoint()
{
delete[] points;
points = NULL;
}
private:
int *points;
You would achieve the same by using some std::vector or std::array instead of the C-style array and you wouldn't have to take care of the memory management on your own:
MyDynamicPoint(int N) : points(std::vector<int>(N, 0)) { }
private:
std::vector<int> points;
the std::vector object will take care of memory management for you.
And last thing: when you dynamically allocate an element and store it into the container:
myList.push_back(new MyDynamicPoint(8));
you need to free this memory on your own, erasing the pointer from the list is not enough:
list<MyDynamicPoint*>::iterator it;
...
delete *it;
myList.erase(it);
So whatever you want to achieve, always prefer objects with automatic storage duration if the situation allows it. There's nothing worse than being forced to taking care of memory management manually and dealing with unpleasant problems such as memory leaks later.
QUESTION 1a: do I need to do anything else to the erased object or will the memory be taken care of?
You don't need to do anything.
QUESTION 1b: if the program ends, do I need to do something with the remaining objects in the list? Do I need to delete them all and deal with their memory somehow?
You don't need to do anything.
QUESTION 2a - Is the above correct?
The code is not correct. You're violating The Rule of Three. In particular, the automatically-generated MyDynamicPoint's copy constructor and assignment operator will make a bitwise copy of the points pointer. If you copy an instance of MyDynamicPoint, you'll end up with two object sharing the same points pointer:
When one of the objects goes of scope, the other becomes unusable.
When the second object goes out of scope, its destructor will attempt to free memory that's already been freed. This is undefined behaviour.
I.e. Because this new version of the class would contain some dynamically assigned memory, does this mean I have to create a list of pointers to objects, not the objects themselves?
No, it does not mean that. In fact, you should probably continue to store objects by value. However, you do need to fix the rule of three.
QUESTION 2b - Given that I have just erased the pointer from the list, where do I call delete to deal with the fact there is now dynamic memory to be deleted in the objects? Or does the erase method of stl list call the destructor of the object, taking care of it?
Since you have a list of raw pointers, the destructors will not be called automatically. The easiest way to fix that is to either store objects by value, or use std::unique_ptr or std::shared_ptr instead of raw pointers.
To question 1, there is nothing you need to do. As you store the objects by value the compiler and the library will handle everything.
However, when you store pointer as in the second case, you need to delete those pointers that you have allocated with new, or you will have a memory leak.
And you have to delete the pointers before doing the erasing, as that can invalidate the iterator:
delete *it;
myList.erase(it);
I think following should work
MyPoint* ptr = myList.back();
delete ptr;
myList.pop_back();
OR
MyPoint* ptr = myList.back();
delete ptr;
myList.erase(ptr);
I've defined a C++ class with the following header file:
class EarleyParser
{
public:
EarleyParser();
virtual ~EarleyParser();
void initialize( string filePath, bool probabilityParse );
private:
bool probabilityParser;
typedef unordered_map< string, list<Production>* > productionHashTable;
productionHashTable earlyHashTable;
};
As you can see a member element of the class is an unordered_map whose key element is a string and content element is a pointer to a list of objects of another class named Production (don't mind it, it could be anything).
My question is if I should leave it to the default destructor to free memory allocated, or if I should manually inspect the hash table and delete all of its elements.
In the second case what would be the procedure? Calling this for each element will be ok?
EarleyParser::productionHashTable::const_iterator got = this->earlyHashTable.find( "key" );
delete[] got->second;
You need to clarify who owns the list<Production> objects owned by EarlyParser. If EarlyParser owns them, then you need to free the resources. You can do it by iterating over the list and calling delete on each dereferenced iterator (not delete[]). Or you can store unique_ptr<list<Production>> instead. On the other hand, the simplest solution is to store list<Production> unless you really have very strong reasons for storing pointers.
If you're going to store pointers to anything in your map, you'll have to manually go through the map and delete each one. Normally in a class you'd stick to RAII (Resource Acquisition is Initialization) and construct things in the constructor and destroy in the destructor
for (;;)
delete map->second; //it's not an array of lists
However a pointer to a container is NOT a good idea. Why do you do need a pointer? What problem are you trying to solve using a pointer to a list?
Using a smart pointer like std::unique_ptr is a much better idea than raw pointers. Raw pointers should be a last resort, not the first thing you grab when you can't think of anything better.
Use a:
typedef unordered_map< string, std::unique_ptr<list<Production> > > productionHashTable;
instead. Then you don't need to worry about managing memory.
The compiler synthesized destructor is not going to delete dynamically allocated lists you put in your map, so you have to do it yourself. In this case you can just iterate through your map and delete the second member of each element:
EarleyParser::~EarleyParser() {
for ( productionHashTable::iterator i = earlyHashTable.begin(); i != earlyHashTable.end(); ++i )
delete i->second;
}
A better approach would be to put lists in your map rather than pointers to lists. In that case the compiler would automatically take care of destruction, as in:
typedef unordered_map< string, list<Production> > productionHashTable;
Unordered_map's destructor actually calls the destructors of the object it has, which means that the destructor's of the lists will be called.
The destructor of std::list has this note:
Note, that if the elements are pointers, the pointed-to objects are not destroyed.
So this means, you will have to clear that memory yourself. Yes, going through the container and deleting elements 1by1 is fine. As other answerers mentioned, holding pointers like this is not a good idea though.
Since you're using a raw pointer to the std::list you'll have to delete it yourself either during the lifecycle of the map or when you clean up the EarleyParser object in its destructor.
You could use something like this in your destructor:
for ( auto it = productionHashTable.begin();
it != productionHashTable.end(); ++it )
{
delete it->second;
}
productionHashTable.clear()
Note that the last line isn't strictly necessary as it will be cleared anyway as the EarleyParser object is destructed but clearly you mustn't use the values in the map after you've deleted them!
How does container object like vector in stl get destroyed even though they are created in heap?
EDIT
If the container holds pointers then how to destroy those pointer objects
An STL container of pointer will NOT clean up the data pointed at. It will only clean up the space holding the pointer. If you want the vector to clean up pointer data you need to use some kind of smart pointer implementation:
{
std::vector<SomeClass*> v1;
v1.push_back(new SomeClass());
std::vector<boost::shared_ptr<SomeClass> > v2;
boost::shared_ptr<SomeClass> obj(new SomeClass);
v2.push_back(obj);
}
When that scope ends both vectors will free their internal arrays. v1 will leak the SomeClass that was created since only the pointer to it is in the array. v2 will not leak any data.
If you have a vector<T*>, your code needs to delete those pointers before delete'ing the vector: otherwise, that memory is leaked.
Know that C++ doesn't do garbage collection, here is an example of why (appologies for syntax errors, it has been a while since I've written C++):
typedef vector<T*> vt;
⋮
vt *vt1 = new vt, *vt2 = new vt;
T* t = new T;
vt1.push_back(t);
vt2.push_back(t);
⋮
delete vt1;
The last line (delete vt1;) clearly should not delete the pointer it contains; after all, it's also in vt2. So it doesn't. And neither will the delete of vt2.
(If you want a vector type that deletes pointers on destroy, such a type can of course be written. Probably has been. But beware of delete'ing pointers that someone else is still holding a copy of.)
When a vector goes out of scope, the compiler issues a call to its destructor which in turn frees the allocated memory on the heap.
This is somewhat of a misnomer. A vector, as with most STL containers, consists of 2 logical parts.
the vector instance
the actual underlying array implementation
While configurable, #2 almost always lives on the heap. #1 however can live on either the stack or heap, it just depends on how it's allocated. For instance
void foo() {
vector<int> v;
v.push_back(42);
}
In this case part #1 lives on the stack.
Now how does #2 get destroyed? When a the first part of a vector is destroyed it will destroy the second part as well. This is done by deleting the underlying array inside the destructor of the vector class.
If you store pointers in STL container classes you need to manually delete them before the object gets destroyed. This can be done by looping through the whole container and deleting each item, or by using some kind of smart pointer class. However do not use auto_ptr as that just does not work with containers at all.
A good side effect of this is that you can keep multiple containers of pointers in your program but only have those objects owned by one of those containers, and you only need to clean up that one container.
The easiest way to delete the pointers would be to do:
for (ContainerType::iterator it(container.begin()); it != container.end(); ++it)
{
delete (*it);
}
Use either smart pointers inside of the vector, or use boost's ptr_vector. It will automatically free up the allocated objects inside of it. There are also maps, sets, etc.
http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/ptr_vector.html
and the main site:
http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/ptr_container.html
As with any other object in the heap, it must be destroyed manually (with delete).
To answer your first question:
There's nothing special about STL classes (I hope). They function exactly like other template classes. Thus, they are not automatically destroyed if allocated on the heap, because C++ has no garbage collection on them (unless you tell it to with some fancy autoptr business or something). If you allocate it on the stack (without new) it will most likely be managed by C++ automatically.
For your second question, here's a very simple ArrayOfTen class to demonstrate the basics of typical memory management in C++:
/* Holds ten Objects. */
class ArrayOfTen {
public:
ArrayOfTen() {
m_data = new Object[10];
}
~ArrayOfTen() {
delete[] m_data;
}
Object &operator[](int index) {
/* TODO Range checking */
return m_data[index];
}
private:
Object *m_data;
ArrayOfTen &operator=(const ArrayOfTen &) { }
};
ArrayOfTen myArray;
myArray[0] = Object("hello world"); // bleh
Basically, the ArrayOfTen class keeps an internal array of ten Object elements on the heap. When new[] is called in the constructor, space for ten Objects is allocated on the heap, and ten Objects are constructed. Simiarly, when delete[] is called in the destructor, the ten Objects are deconstructed and then the memory previously allocated is freed.
For most (all?) STL types, resizing is done behind the scenes to make sure there's enough memory set asside to fit your elements. The above class only supports arrays of ten Objects. It's basically a very limiting typedef of Object[10].
To delete the elements pointed at, I wrote a simple functor:
template<typename T>
struct Delete {
void operator()( T* p ) const { delete p; }
};
std::vector< MyType > v;
// ....
std::for_each( v.begin(), v.end(), Delete<MyType>() );
But you should fallback on shared pointers when the vector's contents are to be ... ehm... shared. Yes.
A functor that deletes pointers from STL sequence containers
The standard STL containers place a copy of the original object into the container, using the copy constructor. When the container is destroyed the destructor of each object in the container is also called to safely destroy the object.
Pointers are handled the same way.
The thing is pointers are POD data. The copy constructor for a pointer is just to copy the address and POD data has no destructor. If you want the container to manage a pointer you need to:
Use a container of smart pointers. (eg shared pointer).
Use a boost ptr container.
I prefer the pointer container:
The pointer containers are the same as the STL containers except you put pointers into them, but the container then takes ownership of the object the pointer points at and will thus deallocate the object (usually by calling delete) when the container is destroyed.
When you access members of a ptr container they are returned via reference so they behave just like a standard container for use in the standard algorithms.
int main()
{
boost::ptr_vector<int> data;
data.push_back(new int(5));
data.push_back(new int(6));
std::cout << data[0] << "\n"; // Prints 5.
std::cout << data[1] << "\n"; // Prints 6.
} // data deallocated.
// This will also de-allocate all pointers that it contains.
// by calling delete on the pointers. Therefore this will not leak.
One should also point out that smart pointers in a container is a valid alternative, unfortunately std::auto_ptr<> is not a valid choice of smart pointer for this situation.
This is because the STL containers assume that the objects they contain are copyable, unfortunately std::auto_ptr<> is not copyable in the traditional sense as it destroys the original value on copy and thus the source of the copy can not be const.
STL containers are like any other objects, if you instantiate one it is created on the stack:
std::vector<int> vec(10);
Just like any other stack variable, it only lives in the scope of the function it is defined in, and doesn't need to be manually deleted. The destructor of STL containers will call the destructor of all elements in the container.
Keeping pointers in a container is a dicey issue. Since pointers don't have destructors, I would say you would never want to put raw pointers into an STL container. Doing this in an exception safe way will be very difficult, you'd have to litter your code with try{}finally{} blocks to ensure that the contained pointers are always deallocated.
So what should you put into containers instead of raw pointers? +1 jmucchiello for bringing up boost::shared_ptr. boost::shared_ptr is safe to use in STL containers (unlike std::auto_ptr). It uses a simple reference counting mechanism, and is safe to use for data structures that don't contain cycles.
What would you need for data structures that contain cycles? In that case you probably want to graduate to garbage collection, which essentially means using a different language like Java. But that's another discussion. ;)