Destroying a vector of vectors - c++

I'm working on a Matrix class that is implemented with a vector of vectors like so:
class Matrix {
private:
int r, c;
std::vector<std::vector<double> > grid;
public:
//things
Currently I am implementing the destructor, and had a thought about it. Before I (smartly) made the switch to the std::vector I was using a double ** grid. That meant a fair bit of new calls since each pointer pointed to an array (which are also pointers I believe...or errors I encountered have suggested anyhow...). Regardless, the destructor looked like:
Matrix::~Matrix() {
for (int i = 0; i < r; i++) {
delete [] grid[i]
delete [] grid
Now I am trying to replicate that (perhaps unnecessarily?) and have the following:
Matrix::~Matrix() {
std::vector<std::vector<double> >::iterator it = this->grid.begin();
for (it; it != this->grid.end(); it++) {
(*it).clear()
this->grid.clear();
std::vector<std::vector<double> >().swap(this->grid);
and
Matrix::~Matrix() {
this->grid.clear();
std::vector<std::vector<double> >().swap(this->grid);
My inclination is to go with the latter, since clear() should completely destroy the internal vectors (not just the contents of the internal vectors) and then the copy and swap idiom-ish effect of the temporary vector to deallocate the memory of the original outer vector. The former makes me think that I clear() the contents of each internal vector, but am left with n-number of empty, still in memory, vectors and would have to call the temporary swap mechanic on each one (and thus potentially [untested] impacting my iterator).
Does calling clear() on the outer vector completely deallocate the memory used for the internal vectors by calling their destructor? I am not sure if their destructor deallocates in a manner that the swap idiom does.

Pay attention, this destructor is trickier than you think. Here we go:
⁣
Okay, actually, it's not. You can thank the rule of zero for this nimble implementation. Since std::vector is a well-behaved class (template) that correctly manages its resources through RAII, the default-generated destructor for your class does the right thing™ without you typing anything.
If, for any reason, you still need an explicit signature for that destructor, you can use the following syntax inside your class:
~Matrix() = default;
Or, if you need the definition to be out-of-line, declare the destructor normally but define it thusly:
Matrix::~Matrix() = default;

You don't need to write explicit destructor. default destructor sequence will take care of destruction part when you go out of scope of this 2D vector definition. Each element of 2D vector is a 1D vector and each element of 1D vector is double , so default destruction sequence will first destroy grid[0] as shown in the below figure, which in turn destroy each double element stored in grid[0], after that it will repeat the same for grid[1] and so on.
_____
_____ grid[0] of doubles |_|_|_|....
|_____ grid[1] of double
grid--> |_____ grid[2] of double
|_____ grid[3] of double
|_____ grid[4] of double

Related

Does delete[] work properly with generic arrays? If so why does using std::vector::erase on it cause error in freeing memory

I was trying to work with arrays that are circular, and so ended up writing a CircularArray class for which I have attached the code. It uses a generic pointer for an array.
When I try creating a list of such circular arrays using std::vector, I face a problem when I try to use erase on it.
I don't see why this should be the case as I think the destructors and copy constructor work well enough normally.
Can someone please help with this?
Code:
CircularArray Class
template<class T> class CircularArray
{
//Class denoted by 'T' is expected to have a functional assignment operator, i.e. operator=(const T& ext) {} in place
protected:
int size=0;
int ori=0;
T* array;
private:
int pos=0;
public:
CircularArray() : CircularArray(0) {}
CircularArray(int s) {size=s;array=new T[s];}
CircularArray(T* ptr,int s)// : CircularArray(s)
{
size=s;array=new T[s];
for(int i=0;i<size;i++)
array[i]=ptr[i];
}
CircularArray(const CircularArray<T>& arr) : CircularArray(arr.size)
{
for(int i=0;i<size;i++)
array[i]=arr.array[i];
}
~CircularArray() {delete[] array;}
...
Testing Code
int main()
{
std::vector<CircularArray<int>> test;
int *a1=new int[3] {1,2,3},*a2=new int[3] {1,2,3},*a3=new int[3] {1,2,3};
CircularArray<int> n1(a1,3),n2(a2,3),n3(a3,3);
test.push_back(n1);
test.push_back(n2);
test.push_back(n3);
test.erase(test.begin()+1);
for(auto v : test)
{
for(int i=0;i<3;i++)
cout << v[i];
cout << "\n";
}
}
This program gives bad output after encountering the deleted part of the vector. Valgrind says that there is a memory corruption in trying to read freed memory.
What is wrong?
Vector elements must be copy/move assignable, yet you are relying on the default copy assignment operator which does not create any fresh memory. Your assigned objects all share the same memory space, later resulting in a double free.
Your constructors are good but you'll need a copy/move assignment operator too.
Read about the Rule of Five.
Also consider just using a std::vector for backing storage; it'll be much simpler.
Does delete[] work properly with generic arrays?
Yes.
Your (implicitly generated) copy and move assignment operator are wrong. They will copy the member pointer. Then you have two pointers to the same array, and one destructor deletes it once, and another deletes it for a second time, which leads to undefined behaviour.
When manually managing dynamic resource, it is essential to keep track of ownership, and make sure that it is released exactly once. A typical solution is to use a smart pointer. Your class has unique ownership (or it would have, if it didn't accidentally share the ownership in the assignment operators) of the dynamic array, so a unique pointer would be an appropriate choice.
On the other hand, you could use a vector container instead of a smart pointer.

When to delete elements added to std::vector?

I'm new to C++ and have a question regarding memory management.
In the header, I have this:
std::vector<Obstacle::Obstacle*> obstacles;
and in the .cpp I do this:
Circle *circle = new Circle(x, y, radius);
obstacles.push_back(circle);
where Circle is a subclass of Obstacle.
My question is when should I call delete on the elements which are in the vector? I have heard each new should be balanced by a delete. Do I need to in the destructor loop through the vector and call delete on each element? Isn't there a more elegant way?
Thanks
You have to call delete on the elements before you clear the vector, or before the vector goes out of scope iff the vector owns the objects pointed at. A more elegant solution is to have the vector hold smart pointers. The particular type of smart pointer should depend on the ownership policy.
For example, a vector owning the pointed-at objects should use C++11 std::unique_ptr:
std::vector<std::unique_ptr<Obstacle>> obstacles;
Of course, all of the above is under the assumption that you actually have strong reasons to use pointers. Often the best solution is the simplest ones: hold items by value:
std::vector<SomeType> things;
Note that this doesn't apply in your case, where you are storing pointers to objects derived from a base class, since storing values of base type would result in object slicing.
Edit: One simple way to ensure the elements are deleted when the vector goes out of scope is to write a scope guard class:
template <typename CONTAINER>
struct PtrContainerGuard
{
PtrContainerGuard(CONTAINER& container) : c_(container) {}
~PtrContainerGuard()
{
for (typename CONTAINER::iterator it = c_.begin(); it != c_.end(); ++it)
delete (*it);
}
private:
CONTAINER& c_;
}
then
std::vector<Obstacle*> obstacles;
PtrContainerGuard<std::vector::Obstacle*> p(obstacles);
Why not use shared_ptr? You don't have to create new objects and worry about deleting them if you use them.
typedef shared_ptr<Obstacle> ObstaclePtr;
int main()
{
std::vector<ObstaclePtr> obstacles;
//Create objets using shared_ptr and push them in vector
ObstaclePtr obstacle1(new Circle());
obstacles.push_back(obstacle1);
ObstaclePtr obstacle2(new Circle());
obstacles.push_back(obstacle2);
//When vector obstacles goes out of scope here, all circles inside are destructed!
}
Yes, there is a more elegant way. Throw away all your pointers.
std::vector<Obstacle::Obstacle> obstacles;
Circle circle(x, y, radius);
obstacls.push_back(circle);
Nothing was new'ed, nothing needs to be deleted, you save a memory allocation, and access to the objects stored in the vector becomes more efficient.
Also, your code will no longer make the eyes bleed of more experienced C++ developers.
All in all, I call that a win. :)

Why does my class's destructor get called when I add instances to a vector?

It seems that every time I add an object to the vector m_test, the destructor method is called. Am I missing something? How can I prevent this from happening?
class TEST
{
public:
TEST();
~TEST();
int * x;
};
TEST::TEST()
{
}
TEST::~TEST()
{
... it is called every time I push_back something to the vector ...
delete x;
}
vector<TEST> m_test;
for (unsigned int i=0; i<5; i++)
{
m_test.push_back(TEST());
}
The problem here is that you're violating the Rule of Three. Your class has a destructor so you need a copy-constructor and an assignment operator, too. Alternatively, you could not allow your class to be copied (for example by making T(T const&) and T& operator=(T const&) private, or by deriving from boost::noncopyable), and then resize the vector instead of using push_back.
In the first case, you can just push_back your class as you usually would. In the second, the syntax would be something like
std::vector<TEST> vec(5);
// vec now has five default-constructed elements of type TEST.
Not doing either of these things is a bad idea, as you are very likely to run into double deletion issues at some point -- even if you think you'll never copy or assign a TEST where x != nullptr, it's much safer to explicitly forbid it.
By the way, if you have member pointers that should be deleted when an object goes out of scope, consider using smart pointers like scoped_ptr, unique_ptr and shared_ptr (and maybe auto_ptr if you're unable to use Boost or C++11).
It's not called when you push_back, it's called when the temporary is destroyed.
To fix it in your example:
TEST test;
for (int i = 0; i < 5; ++i)
{
m_test.push_back(test);
}
Should only call it once.
Your code is creating a temporary TEST within the loop, using it in push_back, then that temporary is going out of scope when the loop ends/repeats and getting destroyed. That occurs exactly as it should, since the temporary TEST needs cleaned up.
If you want to avoid that, you need to do anything else but make a temporary object for each push. One potential solution is to:
vector<TEST> m_test(5); // Note reserving space in the vector for 5 objects
std::fill(m_test.begin(), m_test.end(), TEST()); // Fill the vector with the default ctor
Depending on how your STL is optimized, this may not need to make multiple copies.
You may also be able to get better handling if you implement a copy constructor in your TEST class, like:
TEST::TEST(const TEST & other)
{
x = new int(*other.x); // Not entirely safe, but the simplest copy ctor for this example.
}
Whether this is appropriate, or how you handle it, depends on your class and its needs, but you should typically have a copy constructor when you have defined your own regular constructor and destructor (otherwise the compiler will generate one, and in this case, it will result in copied and hanging pointers to x).
To avoid destruction of a temporary and to avoid copy constructors, consider using vector::resize or vector::emplace_back. Here's an example using emplace_back:
vector<TEST> m_test;
m_test.reserve(5);
for ( uint i=0; i<5; i++ )
{
m_test.emplace_back();
}
The vector element will be constructed in-place without the need to copy. When vt is destroyed, each vector element is automatically destroyed.
c++0x is required (use -std=c++0x with gnu). #include <vector> is of course also required.
If a default constructor is not used (for example, if the TEST::x was a reference instead of a pointer), simply add arguements to the call to emplace_back() as follows:
class TEST
{
public:
TEST( int & arg) : x(arg) {;} // no default constructor
int & x; // reference instead of a pointer.
};
. . .
int someInt;
vector<TEST> m_test;
m_test.reserve(5);
for ( uint i=0; i<5; i++ ) {
m_test.emplace_back( someInt ); // TEST constructor args added here.
}
The reserve() shown is optional but insures that sufficient space is available before beginning to construct vector elements.
vector.push_back() copies the given object into its storage area. The temporary object you're constructing in the push_back() call is destroyed immediately after being copied, and that's what you're seeing. Some compilers may be able to optimize this copy away, but yours apparently can't.
In m_test.push_back(TEST());, TEST() will create an temporary variable. After the vector copy it to its own memory, the temporary variable is destructed.
You may do like this:
vector<TEST> m_test(5, TEST());
The destructor is not only being called for the temporary variable.
The destructor will also get called when the capacity of the vector changes.
This happens often on very small vectors, less so on large vectors.
This causes:
A new allocation of memory (size based on a growth metric, not just size+1)
Copy of the old elements into the new allocation
Destruction of the elements in the old vector
Freeing of the old vector memory.
Copy construction of the new item onto the end of the new new vector.
See the third answer here:
Destructor is called when I push_back to the vector

A vector in a struct - best approach? C++

I am trying to include a vector in my struct.
Here is my struct:
struct Region
{
bool hasPoly;
long size1;
long size2;
long size3;
long size4;
long size5;
long size6;
//Mesh* meshRef; // the mesh with the polygons for this region
long meshRef;
std::vector<int> PVS;
} typedef Region;
Is the vector in this declaration valid or would it make more sense to do a pointer to a vector. In the case of a pointer to a vector, do I need to allocate a new vector. How would I accomplish this?
Thanks!
Edit: The problem is that it ends up causing an error that points to xmemory.h, a file included with the MSVC++ platform.
void construct(pointer _Ptr, _Ty&& _Val)
{ // construct object at _Ptr with value _Val
::new ((void _FARQ *)_Ptr) _Ty(_STD forward<_Ty>(_Val)); // this is the line
}
Interestingly, it does not happen if I allocate it outside of the struct and simply in the function I use. Any ideas?
You can write it like this without the typedef:
struct Region
{
bool hasPoly;
long size1;
long size2;
long size3;
long size4;
long size5;
long size6;
long meshRef;
std::vector<int> PVS;
}; // no typedef required
To answer your questions:
Is the vector in this declaration valid
Yes, it is.
or would it make more sense to do a pointer to a vector.
No, probably not. If you did then you would have to implement copy constructor, assignment operator and destructor for the copy behavior. You would end up with the same but it would be extra work and potentially introduce bugs.
In the case of a pointer to a vector, do I need to allocate a new vector. How would I accomplish this?
You would need to implement the copy constructor, the copy assignment operator and the destructor:
// Copy constructor
Region(const Region & rhs) :
hasPoly(rhs.hasPoly),
// ... copy other members just like hasPoly above, except for PVS below:
PVS(new std::vector<int>(*rhs.PVS))
{
}
// Copy assignment operator
Region & operator=(const Region & rhs)
{
if (this != &rhs)
{
hasPoly = rhs.hasPoly;
// ... copy all fields like hasPoly above, except for PVS below:
delete PVS;
PVS = new std::vector<int>(*rhs.PVS);
}
return *this;
}
// Destructor
Region::~Region()
{
delete PVS;
}
Bottom line: your code is fine. You don't need to change it.
EDIT: Fix assignment operator: check for comparison against this and return *this.
It makes complete sense to do that and you don't need new in any respect, unless you actually want to alias a separate vector. In addition, you don't need any typedef stuff going on here.
It depends on how you use it.
If you want to copy the vector and data when copying the Region struct, then leave it as a non-pointer.
If you don't want it copied over, then you will want some sort of pointer to a vector.
If you use a pointer to a vector, you should be very careful about allocation/deallocation exception safety. If you can't scope your allocation in an exception safe way, then you'll leave a potential for memory leaks.
A couple options are:
Make sure that the code that allocates the vector (and uses the Region) also deallocates the vector, and is itself exception safe. This would require the Region to only exist inside that code's scope.
You could do this by simply allocating the vector on the stack, and pass that to the pointer in the Region. Then make sure you never return a Region object above that stack frame.
You could also use some sort of smart pointer -> vector in your Region.
The vector is fine. Be aware that if you copy this struct, then the vector will be copied with it. So in code with particular performance constraints, treat this struct the same way that you'd treat any other expensive-to-copy type.
In production code, some people would prefer you to use the class keyword rather than the struct keyword to define this class, since the vector member makes it non-POD. If you're the author of your own style guide there's nothing to worry about.
The typedef is wrong, though, just write struct Region { stuff };

Vectors within classes: handling copy constructor and destructor (C++)

Take a simple class with the "big 3" (constructor, copy constructor, destructor):
#include <vector>
using namespace std; //actually goes in the C file that links to this header file
...
class planets(){ //stores mass and radii data for planets in a solar system.
public:
vector <double> mass;
vector <double> radius;
//constructor
planets( int numObj ){
for(int i=0; i<numObj; i++){
mass.push_back(8.0); //some default values.
radius.push_back(2.0);
}
}
//copy constructor
planets(const planets &p){
vector <double> mass(p.mass); //copy vectors into new class.
vector <double> radius(p.radius);
}
//destructor
~planets(){
delete mass; //ERROR: (...) argument given to ‘delete’, expected pointer
~radius(); //also causes error: no match for call to(...)
}
}
I plan on making a vector of planets, thus the need for the "big 3":
vector <planets> stars;
stars.push_back(planets(5)); //5 hypothetical planets of alpha centauri
stars.push_back(planets(8)); //our solar system. Used to be nine.
///etc.
How do I delete the mass and radius vectors properly, to avoid memory leaks (do I even have to)?
No, you don't need to do anything because you aren't managing any resources. You only write the Big Three when you're managing a resource, but vector is doing that. It's the one with the Big Three properly written, you just use it.
This is why the single responsibility principle is key in resource management: once you have some class that properly manages a resource, you can simply use it without ever worrying about that resource again. Always split resource management from resource use.
The reason you need the Big Three written in a managing class is because the default special members typically do the wrong thing (they copy, assign, destruct values instead of what the values manage/point at.) But once you're resource is wrapped up (like in a std::vector), everything is just fine. The defaults will copy vector, but that copying is correctly written.
By the way, the Big Three is in the context of managing resources (copying and destroying resources), not created them. So it would be copy-constructor, copy-assignment, and destructor, not default constructor.
For your information, here's how you would do it:
class planets
{
public:
// ...
//copy constructor
planets(const planets &p) : // use an initialization list to initialize
mass(p.mass), // copy-construct mass with p.mass
radius(p.radius) // copy-construct radius with p.radius
{
// what you had before just made a local variable, copy-constructed
// it with p.xxx, then got released (nothing happened to your members)
}
//destructor
~planets()
{
// nothing to do, really, since vector destructs everything
// right for you, but you yes, you would delete any resources
// you managed here
}
};
But don't forget the copy-assignment operator. I recommend the copy-and-swap idiom, and leave that as an exercise for you.
(Remember you don't actually need these, though.)
The 'big three' aren't what you say they are. They are: copy constructor, copy assignment operator and destructor.
vector instances are already copiable and assignable, you don't have to do anything special so with two members of type vector<double> you don't need to provide custom implementations of the big three.
Your copy constructor is incorrect, it doesn't copy the source vectors in to the new class, it just constructs function locals from them which are then discarded. This creates local variables called mass and radius which mask the member variables with the same name.
planets(const planets &p){
vector <double> mass(p.mass); //copy vectors into new class.
vector <double> radius(p.radius);
}
More correct (but unnecessary) would be:
planets(const planets &p)
: mass(p.mass) //copy vectors into new class.
, radius(p.radius)
{
}
Similarly your destructor body should be empty. You only delete pointers which have been allocated with new. As you have straight member variables no special action is required.
You don't have to implement any destructor for your class. The vectors will be automatically destroyed. This is related to the Resource Acquisition Is Initialization pattern.
Your class can be simplified too:
class planets()
{ //stores mass and radii data for planets in a solar system.
public:
std::vector<double> mass;
std::vector<double> radius;
//constructor
planets( int numObj )
{
for(int i=0; i<numObj; i++)
{
mass.push_back(8.0); //some default values.
radius.push_back(2.0);
}
}
}
Your class does not contain any resources (ie pointers)
Therefore you do not need to explicitly manage them. Each class is supposed to know how to:
Copy Itself
Be assigned over
Destroy itselft
The compiler generated copy constructor assignment operator and destructor will automatically call these operations on any member variables (mass and radius) so you don't need too. So in your case the std::vector knows how to correctly do all three operations and therefore you do not need to add any extra code.
No - you don't have to. member variable's destructors are automatically invoked after the containing object's destructor.
In your particular situation you don't have to! You're not storing pointers in the vector. You're not storing pointers to vectors in your planets class(that is you've not dynamically allocated the vector<> object so why trying to delete it).
As you didn't newed mass, you don't need to delete it.
Also, the destructors of mass and radius will be called automatically, you don't need to call them explicitely
~planets(){
mass.clear();
radius.clear();
}
the above should be enough as your member vector objects do not have any pointers.