I am defining a vector as a private variable of a class Grid. Class Points has only two instance vars that are all ints but the number of points will only be known when I read this in from the file, so I guess I have to make Points dynamically with new which means I have to destroy them later. Did I initialize constructor correctly and When writing a destructor for Grid do I need to write a destructor for vector like this: ~vecotr() or with delete or using iterator?
class Grid{
public:
// initialize vector with 3 points with val 0.
Grid(vector<Points> v) : vector<Points>(3, 0) {}; // is this right
// first option
~Grid() {
~vector<Points>(); // not sure how to destroy vector<Points>;
}
// second option
~Grid() {
delete v_points;
}
// third option
~Grid() {
for (vector<Points>::iterator it = v_points.begin(),
vector<Points>::iterator it_end = v_points.end(); it != it_end; it++)
}
private:
vector<Points> v_points;
};
Which option should I use and did I initialize constructor correctly?
If object is not allocate with new, you do not need to explicitly destroy it.
The member objects will be automatically destroyed in the reverse order of their declaration. In your case there is no need to even create a destructor as the automatic one will suffice.
If for some reason you do have member objects allocated with new, you also have to create custom copy construct and assignment operator otherwise you run into troubles of sharing the same member object across multiple instances.
I will reply because predecessors answered only to the question from topic while you are asking more questions and I will also give some advice. In the remainder of this post we will assume that if Points do allocate any dynamic memory, the memory is returned properly when Points are deleted.
Class Points has only two instance vars that are all ints but the
number of points will only be known when I read this in from the file,
so I guess I have to make Points dynamically with new which means I
have to destroy them later.
This comes with contradiction to what you actually do here
class Grid{
public:
// initialize vector with 3 points with val 0.
Grid(vector<Points> v) : vector<Points>(3, 0) {}; // is this right
private:
vector<Points> v_points;
};
because you create vector without new. However this might be OK if we assume that you first get number of Points and then you are about to create a Grid. std::vector is not C array and might be easily resized, assigned and gives much more flexibility. You do not have to create it on heap because you are afraid about size: vector elements are always created on heap, it is just a vector itself that is (if it is) on stack. And this is often exactly what we want (see i.e. RAII). The proper way to initialize a vector would be then
class Grid{
public:
// initialize vector with 3 Points with val Points(0)
Grid(vector<Points> v) : v_points(3, Points(0)) {};
private:
vector<Points> v_points;
};
Note, we do it in initialization list. For POD class members, it makes no difference, it's just a matter of style. For class members which are classes, then it avoids an unnecessary call to a default constructor.
Did I initialize constructor correctly and When writing a destructor
for Grid do I need to write a destructor for vector like this:
~vecotr() or with delete or using iterator?
You don't initialize constructor, rather in constructor initializer list you initialize class members. Since vector is not allocated with new, you will not delete it (call delete). It will be destroyed automatically when Grid is destroyed.
// fourth (and correct) option:
~Grid() {
}
Or just leave out the destructor entirely; the compiler-generated destructor will do the right thing here.
If you create an object with new you must delete it. If you don't, you mustn't.
I am assuming that Points does not have any dynamically allocated memory. If this is the case then all you need is
~Grid() { }
If it does then you need to delete that dynamically allocated memory for each item in the vector (or use smart pointers).
Related
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 have come across an interesting problem. I have a function in C++ that returns a vector filled with classes. Once the vector is returned, it calls deconstructors for each class that is element in the vector.
The problem is an obvious one: the data is destroyed where a class points to the pointers, which get released when the object is destroyed. I can only assume the deconstructors are called because the vector is on the stack, and not on the heap.
So the question is:
Is there anyway to keep returning vector from a function, without it being destroyed? Or would I have to either pass a pointer to return vector as an input to the function?
You can create anything on heap with new. You shouldn't give out from the function the references to your stack objects, as they will be destroyed as soon as the function finishes.
If you prefer your function to return the vector by value, be sure that the objects inside the vector implement copy constructor (and perhaps assignment operator, too, not sure about that). Having that, please do not forget about the Rule of Three.
C++11 should solve your problem using rvalue references. Honestly, I haven't tried it myself, but from what I read it will do exactly what you are trying to do, return the vector without destroying and recreating it (by passing the memory allocated by that vector on to the new vector instead of having the new vector create its own memory and copy the contents over from the old one).
C++ vectors are allocated on the heap. When you return a vector by value a new one will be created with copies of all the elements, then the original elements will be destroyed.
It sounds like you haven't defined your copy constructors properly. For example:
class ThisIsWrong
{
public:
ThisIsWrong()
{
i = new int;
*i = rand();
}
~ThisIsWrong()
{
delete i;
i = nullptr;
}
int value() const
{
return *i;
}
private:
int* i;
};
void foo()
{
vector<ThisIsWrong> wronglets;
wronglets.push_back(ThisIsWrong());
return wronglets;
}
void main()
{
vector<ThisIsWrong> w = foo();
w[0].value(); // SEGFAULT!!
}
You either need to delete the copy and assignment constructors (which will then turn this into a compilation error instead of runtime), or implement them properly.
I have a std::vector of Element*. When will the destructor be called.
How is it different if it is a vector of Element
std::vector<Element*> vect;
..
struct Element
{
Record *elm;
Element(Record *rec)
{
elm = new Record();
//...copy from rec
}
~Element()
{
delete elm;
}
};
I am using the vector as follows:
Element *copyElm = new Element(record);
vect.push_back(copyElm);
In the above code, how can I ensure there's no leak.
You could use a reference-counting pointer-wrapper class in your array, and the items will automatically get deleted whenever there are no more references to them. One such class is boost::shared_ptr. You will also find it in some compiler's shipping C++ libraries because it is being added to a future version of C++.
std::vector<boost::shared_ptr<Element> > vect;
These classes wrap operator ->, etc, so you can use them in most of the same ways that you'd used a normal pointer.
http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/shared_ptr.htm
Whenever you free the class Element instance yourself. The vector will free the vector elements (the pointers), but not the class Element objects pointed to. After all, the vector has no way to know if you have other pointers to the same object.
vector will call release the memory of the object it is holding (i.e. pointers) but will not release the memory of the object it is pointing to. You need to release the memory of the Element object yourself. If it was a vector<Element> then whenever you do a push_back a copy of the element is inserted into the vector. vector guarntess that it will release the memory allocated to this copied object. But be aware with the current definition of Element you will get a seg fault as you have not defined the copy ctor and assignment operator.
EDIT
If you for some reason don't want to use smart pointers, then only option is to write a release function which goes through the entire vector and calls the delete on the stored pointer.
In a vector of Element, the destructor is called a lot. Whenever a node is assigned, the vector is sized down, the vector has to move in memory, or the vector goes out of scope/is destroyed, destructors are called on the elements before they are changed/discarded. Also, the copy constructor is called for assignment, and the default constructor is called to initialize each entry. Sorting such a vector will involve a lot of both copying and destroying.
In a vector of Element* it is never called, unless you call delete yourself.
Take a look at Boost shared_ptr for a saner solution, or unique_ptr if you have a compiler with relatively new features.
Destroying a pointer is always a no-op, and there are several good reasons why.
I'm a bit confused about handling an array of objects in C++, as I can't seem to find information about how they are passed around (reference or value) and how they are stored in an array.
I would expect an array of objects to be an array of pointers to that object type, but I haven't found this written anywhere. Would they be pointers, or would the objects themselves be laid out in memory in an array?
In the example below, a custom class myClass holds a string (would this make it of variable size, or does the string object hold a pointer to a string and therefore take up a consistent amount of space. I try to create a dynamic array of myClass objects within a myContainer. In the myContainer.addObject() method I attempt to make a bigger array, copy all the objects into it along with a new object, then delete the old one. I'm not at all confident that I'm cleaning up my memory properly with my destructors - what improvements could I make in this area?
class myClass
{
private:
string myName;
unsigned short myAmount;
public:
myClass(string name, unsigned short amount)
{
myName = name;
myAmount = amount;
}
//Do I need a destructor here? I don't think so because I don't do any
// dynamic memory allocation within this class
};
class myContainer
{
int numObjects;
myClass * myObjects;
public:
myContainer()
{
numObjects = 0;
}
~myContainer()
{
//Is this sufficient?
//Or do I need to iterate through myObjects and delete each
// individually?
delete [] myObjects;
}
void addObject(string name, unsigned short amount)
{
myClass newObject = new myClass(name, amount);
myClass * tempObjects;
tempObjects = new myClass[numObjects+1];
for (int i=0; i<numObjects; i++)
tempObjects[i] = myObjects[i]);
tempObjects[numObjects] = newObject;
numObjects++;
delete newObject;
//Will this delete all my objects? I think it won't.
//I'm just trying to delete the old array, and have the new array hold
// all the objects plus the new object.
delete [] myObjects;
myObjects = tempObjects;
}
};
An array in C++ is an array of objects laid out in memory.
So for example in:
struct pair {
int x; int y;
};
...
pair array[10];
Each item in the array is going to be with a size of two ints.
If you want an array of pointers you can simply declare one:
pair* array_of_pointers[10];
The string objects have pointers to the variable size part of the string. So they're safe.
In fact they're the important lesson here. Same way you use the string class to avoid excessive memory handling you can use the vector class to avoid all the troubles of handling a dynamic array.
For the case you're doing this as an exercise. Here are a few problems:
newObject needs to be allocated locally, without new. This will make the code correct (as newObject is not a pointer and new returns a pointer) and will also save you the trouble of explicitly handling memory. (On a more advanced note, this makes the code exception safe in one more location)
myObject is never initialized. And you don't use initialization lists in the constructor. The constructor should look like this:
myContainer() : numObjects(0), myObjects(NULL)
{
}
The destructors in the code are exactly as they should be.
No, a dynamic array is not an array of pointers to that type - its a pointer to the first element. The elements are laid out consecutively in memory and are destroyed when the array is delete[]ed.
Thus your deallocation looks fine - you create dynamic arrays of myClass objects so you don't have to delete them individually. You would only have to do this if you had an array of pointers to (dynamically allocated) objects.
There are two definitive errors though:
tempObjects[numObjects] = newObject; // assign a myClass pointer to a myClass instance?
This should be e.g.:
tempObjects[numObjects] = myClass(name, amount);
Also, myObjects is never initialized, which means it contains garbage and dereferencing/using it leads to undefined behaviour.
Finally, unless you are doing this for learning purposes, simply use containers like std::vector that do all the work for you already.
I would expect an array of objects to be an array of pointers to that object type, but I haven't found this written anywhere. Would they be pointers, or would the objects themselves be laid out in memory in an array?
The array will consist of the objects themselves. If you want to have an array of pointer you will have to declare that:
myClass ** tempObjects;
tempObjects = new myClass*[numObjects+1];
I assume you are used to C# or Java? In those languages objects can only be allocated on heap and are always accessed by referenced. It is possible in C++, but in C++ you can also put objects directly on the stack, or directly construct an array of the objects themselves.
In the example below, a custom class myClass holds a string (would this make it of variable size, or does the string object hold a pointer to a string and therefore take up a consistent amount of space?
Number two: The string object itself is constant in size, but has a pointer to a dynamically sized buffer allocated from the heap.
I think the deallocation looks fine. The code could be written more efficient in various ways, but it looks correct.
Try to test it, to see what happens (yes, that may be compiler-specific, but still)...
You could try to add a custom destructor to myClass (even though you don't need one), that increments a "global" counter when called, Then print the counter after deleting the array.
I would expect the destructor of each object to be called. Note that quite often objects are stored "by-pointers" to allow for inherited objects to be put into the array (avoiding "slicing").
This is an extension of this question . I have searched on the web but couldn't find a satisfactory answer.
I have a class A which defines a vector that contains a number of instances of class Region. The memory handling for these Region instances need to be managed by Class A
My questions are:
1. In the following code snippet, do I need to explicitly delete these instances in the desctuctor of class A?
2. Should I create instances as new Region(i) ? Is it better over the first option (not using new) Class A is quite a large object. How should I determine whether to use new or not?
3. If Answer to #2 is yes, how should I delete these instances in the destructor ? delete Region(i) (in a for loop) or delete [] reg?? I am guessing former way is the correct way, but want to confirm.
4. Other than "Region instances are not deleted" , do you see any obvious memory leak... especially in the construction of Region object in A's constructor?
class Region{
public:
Region(int num);
int number;
std::vector <elemt*> elements;
int info;
}
class A{
public:
std::vector<Region> reg;
const int numOfRegions = 100;
}
A::A(){
int i;
for ( i=0; i<numOfRegions; i++){
reg.push_back(Region(i));
}
}
A::~A(){
// How should the elements within vector Region be deleted??
// Should I use "new" to allocate memory to instances of Region()
}
UPDATE:
A BIG Thanks to all who answered!
In the following code snippet, do I need to explicitly delete these
instances in the desctuctor of class
A?
No - they will be automatically deleted for you - if you don't create it with new, you don't delete it.
Should I create instances as new Region(i) ? Is it better over the
first option (not using new) Class A
is quite a large object. How should I
determine whether to use new or not?
The size of A is not an issue. There is no clear answer to this question but the general rule is that if you don't have to create objects dynamically using new, then don't do so.
If Answer to #2 is yes, how should I delete these instances in the
destructor ? delete Region(i) (in a
for loop) or delete [] reg?? I am
guessing former way is the correct
way, but want to confirm.
If you created them using new, you would delete them in a for loop as:
delete reg[i];
reg would have to be a vector of pointers of course. a better option would be to use a vector of smart pointers.
Other than "Region instances are not deleted" , do you see any obvious
memory leak.. especially in the
construction of Region object in A's
constructor?
They are deleted - just not by you. This is known as RAII and is very, very good C++ practice - you should use RAII whenever possible.
No. std::vector stores the Regions as objects and calls the necessary (de)constructors when elements are added/removed/overridden.
No. Only if you declare your vector as std::vector<Region *> reg;. You have to do that if Region is polymorphic or the copy/assignment constructors are expensive (vector copies elements around often).
If you store them as pointers you need to iterate over the reg and delete each element with delete ptr;.
Depending on how you create instances of the elemt-class you may want to add a destructor to Region to destroy these instances.
Inside class A everything seems to be defined OK. (You will need to tidy up the class declaration). This means that everything will be automatically destroyed when an instance of A is destroyed. Yes, and I mean that std::vector reg; destroys itself, and all the copies of Region instances it has responsibility for.
Are you really asking about class Region and its vector which has pointers, which, although you haven't shown any code for might need its pointers deleting?
edit:
( first edit included details of Region, second edit removes them and adds A::addRegions )
I think this is what you are after:
#include <vector>
class Region{
public:
Region(int num);
// Details of Region removed
};
class A{
std::vector<Region> reg;
const int numOfRegions;
public:
A();
// No destructor needed: ~A();
void addRegions(int num);
};
A::A():numOfRegions(100){
for (int i=0; i<numOfRegions; ++i){
reg.push_back(Region(i));
}
}
void A::addRegions(int num)
{
for (int i=0; i<num; ++i){
reg.push_back(Region(i));
}
}
Notice how class A has no destructor.
new
A::addRegions also uses push_back and even now no destructor is needed.
Also notice how class declarations have semi-colons after them, and the constructor for A initialises numOfRegions.
1. The only thing you'll need to explicitly delete here in your example are the elemt* if the they are dynamically allocated. If so, they must be deleted by however owns them. In the case your Region only points to them, you should not delete them in its destructor.
2. First, Your vector is allocated in the stack and will be deallocated without problems. Second, to you use new Region(i) you would need to change your class A declaration. But there is not a necessity for that in your case. A few examples when you should use operator new:
1) the necessity for a more persistent data is required, since your dynamically allocated data will persist until explicitily deallocated (and acessible as long you keep a pointer refering to it)
2) your objects might be too big to be all stored in the stack.
3. If you did use new Region(i), you would to use operator delete at some point, probably on destructor or other cleanup function, to correctly deallocate this.
4. Your constructor would present a problem only if you are creating new elemt directly in your elements vector i.e. elements.push_back(new elemt()), for instance. This is a dangerous design that may cause several memory leaks or risks for seg faults. If you want to allocate them this way, you would need a smart pointer with support for copy mechanics like a shared pointer.