Delete objects from std::vector<elements> and delete the objects itself also

Hey there,

this is more a c++ question.
I am filling a std::vector with some object classes.

like so:

vector <element> elements;
element myElement2;
elements.push_back(myElement2);

I now want to delete the objects when i dont need them anymore from the vector but also delete the element objects them self.

i tried like following:

delete *elements[i];
elements.erase(elements.begin()+i);

I am getting the following error:
sceneGenerator.cpp|44|error: no match for ‘operator*’ in ‘((sceneGenerator)this)->sceneGenerator::elements.std::vector<_Tp, _Alloc>::operator[]<element, std::allocator >(((std::vector::size_type)i))’

But when I write delete elements[i]; it says it wants a pointer.
I am confused, can someone telle me how i can delete the objects itself?

Hello,

If you want to delete the i + 1 element, you can do it like so:

elements.erase(elements.begin() + i);

In general, if you have some doubts about C++, I recommend you have a look at this website. It has always been useful for me.

Thanks for the link. I was there and it helped me a lot.
Deleteing from the vector works fine, but deleteing the element itself brings me errors.
The whole pointer thing really confuses me…

The rule of thumb is calling delete on an object only if you’ve previously instantiated it by calling object = new myClass();. Otherwise there’s no need, in fact it will lead to errors.

In your case it seems you have a vector of objects rather than a vector of pointers to an object. So whenever you call erase on an element, the destructor will be called for you.

Pointers on themselves do not hold an existing element until you explicitely intantiate it, for instance:

vector<element*> elements; // No elements exist, vector empty
elements.push_back(new element()); 
// A new element has been instantiated and it's pointed by the first element in your vector

delete elements[0]; // The element is deleted, pointer is now invalid but still in your vector
elements.erase(elements.begin()); // Now your pointer is erased, your vector is empty

There are plenty of resources on pointers and C++, if you want just don’t use any and you won’t have to delete them! Just use plain objects:

vector<element> elements; // No elements exist, vector empty
elements.push_back(element()); 
// element instantiated and it's the first object in your vector
elements.erase(elements.begin()); // element both erased from vector and destructed for you

Just don’t mix things up :wink: Pointers are a really broad topic and it takes some time to understand them, take a look at this post. There are thousands of webs on pointers including the ofBook! Good luck!

1 Like

Yeah, pointers are my nightmare. IFrom time to time i try to understand them ;).
I just did like you said and it seems to work fine. THANKS! :smile:
But the constructor and destructor are doing strange things. Look at the screenshot.

Sometimes all created objects seem to get a destructor call. And it seems that when the destructor is called the member variables are allready deleted. Any ideas what that might be? Also it seems the destructor is called before creation???
Thanks for the links. I will check them out!

Take into account that passing parameters by value via functions will perform object copies and object copies will delete and create objects:

void foo(myClass obj) // creaste a copy of obj when called
{
    ....
}

void foo(myClass & obj) // This is a reference (yet another pointer) to obj, no copies
{
    ....
}

So calling push_back does more than you’d expect, but that’s just normal.

This tutorial is a great reference when working with vectors. I referred to it a lot when I was trying to wrap my head around them. http://openframeworks.cc/tutorials/c++%20concepts/001_stl_vectors_basic.html

The rule is:
You ‘delete’ it if you create it using ‘new’, otherwise you do not need to.

In your example:

vector <element> elements;
element myElement2;
elements.push_back(myElement2);

You just can do this:

elements.erase(elements.begin()+i);

If you, however, do this:

vector <element *> elements;
element * myElement2 = new element();
elements.push_back(myElement2);

You need to do this:

delete elements[i];
elements.erase(elements.begin()+i);

Another example:
In this case, you do not have to ‘delete’:

void doSomething() {
	element myElement3;
	
	// ... blah blah ...
	
	// with the end of the function, myElement3 will be deleted
}

But in this case, you have to. Otherwise there will be leakage:

void doSomething() {
	element * myElement3 = new element();
	
	// ... blah blah ...
	
	delete myElement3;
}
2 Likes

Hey there,

thanks a lot for the examples and the link. I think i understand it now.
I was a bit stuck in this because i wanted to setup the objects in the vector before putting them into the vector. for this i had to use pointers or copys of the object. Now I create the object in the vector and than call my setup function on the last element of the vector.

What i dont understand is the creation of let me call it ghost or passive copys of the class.

Lets say the class looks like this:

element::element(){
cout << "created" << endl;
}
element::~element(){
cout << "killed" << " " << posZ << endl << endl;
}
void element::setup(float px, float py, float pz){
posX = px;
posY = py;
posZ = pz;
this->setPosition(posX, posY, posZ);
cout << "created and setup" << " " << posZ << endl;
}

And i create the elements in a little sceneGenerator:

void sceneGenerator::setup(float createDistZ, float destroyDistZ, int numElements){
createDistZ_ = createDistZ;
numElements_ = numElements - 1;
destroyDistZ_ = destroyDistZ;
lastDrawPosZ_ = createDistZ_*(numElements_+1);

elements.reserve(numElements_);

//elementDistance_ = 1000;
//myElement.setup(0,0,1000);
for(int i=1; i <= numElements_+1; i++){
    // = new element;
	//myElement2->setup(0,0,i*createDistZ_);
	elements.push_back(element());
	elements[elements.size()-1].setup(0,0,i*createDistZ_);
	//cout << i*createDistZ_ << endl;
}
//cout << elements.size() << endl;

}

It seems that the constructor and destructor are called more than my from the calls in my methods. Did i get that right that c++ is doing that to handle the classes in the vector?

And another thing is that the destructor is always outputting the Z Value of the last created element.
In my case “killed 10000 (posZ)”.
PosZ is not a static variable so it should not be shared between the different elements.

I am confused :open_mouth:

[quote=“rak_multi, post:9, topic:19167”]
elements.push_back(element());
[/quote]what you want to do is
elements.push_back(new element());

when you call elements.push_back(element()) you are creating an object copying it and then destroying the original. in c++11, you can do elements.emplace_back() which will create an element directly in the vector with no copies at all.

Hey Arturo,

thanks for pointing that out. I knew something like this must happen.

I am still not understanding why the output of my destructor equals the value which get set in the last created object.
Its no static variable i define and set it like following:

class element: public ofNode {
private:
    float myPosZ;

public:
    void setup(float px, float py, float pz);
    void customDraw();
    void update();

element();
~element();
};


void element::setup(float px, float py, float pz){
myPosZ = pz;
}
element::~element(){
cout << "killed" << " " << myPosZ << endl << endl;
}

The console window looks like so:

every kill the value is 10000 but it should be 2000,4000,8000 …

When i now close the gl window i see that the right kill messages get printed in the console. killed 2000, killed 4000,
It seems that some Objects stay allive even if the get erased from the vector.

you are not giving any value to that variable in the constructor so it’s not initialized. when you create a new object before copying it into the vector and destroying it, myPosZ can take any value. most probably the object is being created in the same memory space as the previous one and the variable taking the previous value you wrote in that position but it could be anything. try initializing that value to 0 in the constructor and it’ll show as zero in the debug trace when it’s destroyed

I tried to init the variable in the constructor but got the same 10000 output.
I changed everything to a vector of pointers and now it seems to work. Added the deletion of the object itself before deleting the vector item…

delete elements[i];
elements.erase(elements.begin()+i);