is this a valid delete operation in c++? - c++

I have a vector<some_struct&> array in my code, and whenever I want to add some object to my vector I use array.push_back(*new some_struct). now I'm wondering if I should delete every object in my array before clearing my array (using delete &array[i]) or not?

vector<some_struct&> array is invalid, period.
The type (or types) with which you instantiate a Standard Library container must be object types. A reference type (like some_struct&) is not an object type.
By definition, "containers are objects that store other objects" (from §23.1/1 in both C++03 and C++0x). References are not objects.
The behavior is undefined if you instantiate a container with a type that does not meet the requirements that the container imposes: your code may or may not compile and if it does compile, who knows what the result will be; anything could happen..

How does this even compile? That's not legal C++ code on any compiler I've used in the past 5 years.

The vector reference says that push_back copies the data to the container. In your example, not the pointer to, but the contents of each structure would be copied. So if you use *new my_struct, the reference to the memory allocated for the structs will be lost after having used them to pass the data to the container, meaning you need to store those pointers to each of the structs you allocated somewhere to be able to release them, or you will get memory leaks.
If you wanted to keep the pointers, the container should be a vector<some_struct*>, and you could pass new some_struct and should (e.g.) release them with delete array [i].

If your vector is declared vector<some_struct&> array, array.push_back(new some_struct) shouldn't work. array.push_back(some_struct()) will work and in that case you don't need to call delete.

You're going to lose the memory allocated every time you do this. You're essentially creating a copy of that data, but the original is lost in memory somewhere once this process completes. Either keep an external reference to it somewhere which you can delete after you copy it, or use a vector of pointers, not references.

Related

Managing pointers to destroyed objects in a game engine in an elegant way

I'm currently building a game engine, and have run into a bit of a problem. I have found a couple of solution, but it's quite as elegant as I would like them to be.
Here's the issue:
Instantiate Object A in the engine
Get a pointer to Object A - ObjectA*
Destroy Object A
ObjectA* becomes a dangling pointer
Using shared_ptr is a no-go since it can lock objects, which we don't want. There's nothing wrong with Object A being destroyed, I just need a way to check whether it has.
I have two solutions for this issue:
The first is simply to return a surrogate object whenever you want a reference to an object. This surrogate object could have an implicit conversion to a raw pointer, for cases where we know for certain the object is valid. In cases where we keep the reference around for longer, we would use the surrogate object, which is basically just a pointer to a pointer. When the object is destroyed we simply set its pointer to nullptr, which the surrogate would then be able to check for
The second solution is to not return pointers at all. Instead, whenever we want a reference to an object, we pass along the pointer we want it assigned to as a parameter. The engine will then keep said pointer in memory and manually set it to nullptr when the object is destroyed.
Here are the requirements for my preferred elegant solution:
Only uses raw pointers for references
Said raw pointers are returned from function calls (i.e. Ptr* AddCompoenent<>() instead of void AddComponent<>(Ptr*&)
Pointers will become nullptr when the object they point to is destroyed
Is this at all possible?
If you want to return simple pointers, there is no way of collecting all pointers to the object when you deallocate it and setting them to nullptr if you just use normal C++ objects.
There is of course a solution, it's not new, and it's called garbage collection. This is exactly the algorithm you'd need to do it; it analyzes the stack and heap and is able to collect all pointers to your object. Just instead of keeping the object if it finds pointers to it, you want it to set the pointers to nullptr.
Now there are a couple of prerequisites to garbage collection. One is that you must be able to recognize all pointer values on the stack and heap at runtime, so that you can be sure that some data is actually a pointer to your object and not just some integer or other value that happens to hold a value that looks like a pointer to your object. If you still want to have simple pointer types in your code, you need support from your compiler to have that information at runtime – and C++ does not provide it. This is why garbage collection is typically defined for a whole language.
Moreover, the performance implications of using this algorithm are horrendous: Every time you deallocate an object, you would need to analyze all stack and heap. This would mean it runs far more often than a normal gc-based language runs it, and look at their performance losses due to it.

Why is vector of unique_ptr the prefered way to store pointers?

What I have readen say that a common approach to make a vector of pointer that own the pointers, of MyObject for example for simples uses, is vector<unique_pointer<MyObject>>.
But each time we access an element will call unique_ptr::get(). There is also a little overhead.
Why isn't vector of the pointer with "custom deleter", if such a thing exists (I don't have used allocators), more standard? That is, a smart vector instead of a vector of a smart pointer. It will eliminate the little overhead of using unique_ptr::get().
Something like vector<MyObject*, delete_on_destroy_allocator<MyObject>> or unique_vector<MyObject>.
The vector would take the behaviour "delete pointer when destroy" instead of duplicate this behaviour in each unique_ptr , is there a reason, or is just the overhead neglegible ?
Why isn't vector of pointer with "custom deleter", if such a thing exists
Because such a thing doesn't exist and cannot exist.
The allocator supplied to a container exists to allocate memory for the container and (optionally) creates/destroys the objects in that container. A vector<T*> is a container of pointers; therefore, the allocator allocates memory for the pointer and (optionally) creates/destroys the pointers. It is not responsible for the content of the pointer: the object it points to. That is the domain of the user to provide and manage.
If an allocator takes responsibility for destroying the object being pointed to, then it must logically also have responsibility for creating the object being pointed to, yes? After all, if it didn't, and we copied such a vector<T*, owning_allocator>, each copy would expect to destroy the objects being pointed to. But since they're pointing to the same objects (copying a vector<T> copies the Ts), you get a double destroy.
Therefore, if owning_allocator::destruct is going to delete the memory, owning_allocator::construct must also create the object being pointed to.
So... what does this do:
vector<T*, owning_allocator> vec;
vec.push_back(new T());
See the problem? allocator::construct cannot decide when to create a T and when not to. It doesn't know if its being called because of a vector copy operation or because push_back is being called with a user-created T*. All it knows is that it is being called with a T* value (technically a reference to a T*, but that's irrelevant, since it will be called with such a reference in both cases).
Therefore, either it 1) allocates a new object (initialized via a copy from the pointer it is given), or 2) it copies the pointer value. And since it cannot detect which situation is in play, it must always pick the same option. If it does #1, then the above code is a memory leak, because the vector didn't store the new T(), and nobody else deleted it. If it does #2, then you can't copy such a vector (and the story for internal vector reallocation is equally hazy).
What you want is not possible.
A vector<T> is a container of Ts, whatever T may be. It treats T as whatever it is; any meaning of this value is up to the user. And ownership semantics are part of that meaning.
T* has no ownership semantics, so vector<T*> also has no ownership semantics. unique_ptr<T> has ownership semantics, so vector<unique_ptr<T>> also has ownership semantics.
This is why Boost has ptr_vector<T>, which is explicitly a vector-style class that specifically contains pointers to Ts. It has a slightly modified interface because of this; if you hand it a T*, it knows it is adopting the T* and will destroy it. If you hand it a T, then it allocates a new T and copies/moves the value into the newly allocated T. This is a different container, with a different interface, and different behavior; therefore, it merits a different type from vector<T*>.
Neither a vector of unique_ptr's nor a vector of plain pointers are the preferred way to store data. In your example: std::vector<MyObject> is usually just fine, and if you know the size at compile time, try std::array<int>.
If you absolutely need indirect references , you can also consider std::vector<std::reference_wrapper<MyObject>>. Read about reference wrappers here.
Having said that... if you:
Need to store your vector somewhere else than your actual data, or
If MyObjects are very large / expensive to move, or
If construction or destruction of MyObjects has real-world side-effects which you want to avoid;
and, additionally, you want your MyObject to be freed when it's no longer refered to from the vector is gone - the vector of unique pointers is relevant.
Now, pointers are just a plain and simple data type inherited from the C language; it doesn't have custom deleters or custom anything... but - std::unique_ptr does support custom deleters. Also, it may be the case that you have more complex resource management needs for which it doesn't makes sense to have each element manage its own allocation and de-allocation - in which case as "smart" vector class may be relevant.
So: Different data structures fit different scenarios.

deleting a vector of pointers vs. object in c++

I have a vector of pointers to an object (I have them as pointers because I will be swamping the positions around a lot, and I would imagine it would be a lot faster to just swap the pointer, rather than swapping around the whole object.
Anyway, I will ultimately need to delete the vector, but the objects that it points to still need to be valid. The documentation seems to say that it will call the destructor on every object in the vector. This makes sense when it's an array of objects, but if the array is an array of pointers to objects, will the objects that the pointers point to also be deleted, or do I need to delete them manually?
If they are deleted automatically, is the only way to keep the objects around (say they were used in a different vector) is to actually copy the objects to another location, and have the pointers in the vector point to those objects (rather than the originals)?
Thank you.
Calling a destructor on a pointer value does nothing. (On the other hand, calling delete on a pointer value runs the destructor for the pointed-to object, and frees the memory.)
In the case of an array of pointers to objects, you must free the objects manually if that's what you want.
If you have a vector of pointers, the actual objects should still be around if you delete (or clear) the vector.
You could use smart pointers in your vector, such as Boost shared_ptr.
It will indeed destruct any objects in the container. However, since all the objects in your container are pointers, that won't do much of anything.
Reading your question, that sounds like exactly what you want it to do, so you are good.
It does not matter - that's the reason for the delete keyword. If you go out of scope, then the object's destructor is called. If a pointer goes out of scope, then it tends to be a memory leak. The same applies here, so you will not have to do anything special.
They will continue to exist.
Anyway, I will ultimately need to delete the vector, but the objects that it points to still need to be valid. The documentation seems to say that it will call the destructor on every object in the vector. This makes sense when it's an array of objects, but if the array is an array of pointers to objects, will the objects that the pointers point to also be deleted, or do I need to delete them manually?
First, read this: http://crazyeddiecpp.blogspot.com/2010/12/pet-peeve.html
Now ask yourself, does the documentation say that vector deletes every object that every object it contains points at?
If you can answer that question with 'No' then there you have it.
If you can answer that question with 'Yes'...well...try different documentation.

Creating an object on the stack then passing by reference to another method in C++

I am coming from a C# background to C++. Say I have a method that creates a object in a method on the stack, then I pass it to another classes method which adds it to a memeber vector.
void DoStuff()
{
SimpleObj so = SimpleObj("Data", 4);
memobj.Add(so);
}
//In memobj
void Add(SimpleObj& so)
{
memVec.push_back(so); //boost::ptr_vector object
}
Here are my questions:
Once the DoStuff methods ends will the so go out of scope and be popped from the stack?
memVec has a pointer to so but it got popped what happens here?
Whats the correct way to pass stack objects to methods that will store them as pointers?
I realise these are probably obvious to a C++ programmer with some expereince.
Mark
Yes.
The pointer remains "alive", but points to a no-longer-existent object. This means that the first time you try to dereference such pointer you'll go in undefined behavior (likely your program will crash, or, worse, will continue to run giving "strange" results).
You simply don't do that if you want to keep them after the function returned. That's why heap allocation and containers which store copies of objects are used.
The simplest way to achieve what you are trying to do would be to store a copy of the objects in a normal STL container (e.g. std::vector). If such objects are heavyweight and costly to copy around, you may want to allocate them on the heap store them in a container of adequate smart pointers, e.g. boost::shared_ptr (see the example in #Space_C0wb0y's answer).
Another possibility is to use the boost::ptr_vector in association with boost::ptr_vector_owner; this last class takes care of "owning" the objects stored in the associated ptr_vector, and deleting all the pointers when it goes out of scope. For more information on ptr_vector and ptr_vector_owner, you may want to have a look at this article.
To achieve your goal, you should use a shared_ptr:
void DoStuff()
{
boost::shared_ptr<SimpleObj> so(new SimpleObj("Data", 4));
memobj.Add(so);
}
//In memobj
void Add(boost::shared_ptr<SimpleObj> so)
{
memVec.push_back(so); // std::vector<boost::shared_ptr<SimpleObj> > memVec;
}
Yes your so object will be popped off the stack once your function leaves scope. You should create a heap object using new and add a pointer to that in your vector.
As said before, the pointer in your vector will point to something undefined once your first function goes out of scope
That code won't compile because inside the Add function you're trying to trying to push a whole object into a vector that expects a pointer to an object.
If instead you were to take the address of that object and push that onto the vector, then it would be dangerous as the original object would soon be popped off the stack and the pointer you stored would be pointing to uninitialised memory.
If you were using a normal vector instead of a pointer vector then the push_back call would be copying the whole object rather than the pointer and thus it would be safe. However, this is not necessarily efficient, and the 'copy everything' approach is probably not intuitive to someone from the C#, Java, or Python worlds.
In order to store a pointer to an object it must be created with new. Otherwise it will disappear when going out of scope.
The easiest solution to your problem as presented here would be to use std::vector instead of boost::ptr_vector, because this way the push_back would copy the object in the vector

c++ vector of class object pointers

What I am trying to do is essentially create two vectors of objects, where some objects are entered into both lists and some are just entered into one. The first problem I found was that when I used push_back() to add an object into both lists the object was copied so that when I changed it from one list the object did not change in the other. To get around this I tried to create a list of pointers to objects as one of the lists. However when I accessed the pointer later on the data seemed to be corrupted, the data member values were all wrong. Here are some snippets of my code:
Definition of vectors:
vector<AbsorbMesh> meshList;
vector<AbsorbMesh*> absorbList;
...
Adding an object to both:
AbsorbMesh nurbsMesh = nurbs.CreateMesh(uStride, vStride);
// Add to the absorption list
absorbList.push_back(&nurbsMesh);
// Store the mesh in the scene list
meshList.push_back(nurbsMesh);
Accessing the object:
if (absorbList.size() > 0)
{
float receivedPower = absorbList[0]->receivedPower;
}
What am I doing wrong?
There's some details missing, but at a guess.
nurbsMesh goes out of scope between the push_back and the absorbList[0]->receivedPower.
So now your vector of pointers contains a pointer to an object that doesn't exist anymore.
Try adding a copy constructor to your AbsorbMesh class and adding to your vector like this.
absorbList.push_back(new AbsorbMesh(nurbsMesh));
meshList.push_back(nurbsMesh);
don't forget to delete the objects in absorbList, like this
for(vector<AbsorbMesh*>::iterator it = absorbList.begin(); it != absorbList.end(); it++) {
delete it;
}
Or store a shared pointer in your vector instead of a bare pointer. Boost has a good shared pointer implementation if you're interested. See the docs here
If you want to have updates to items in one vector modify objects in the other vector, then you'll need to store pointers in both vectors.
Using your original requirements (updating an item in one vector affects items in the other vector, here's how I'd do it with a boost shared pointer. (WARNING, untested code)
vector<boost::shared_ptr<AbsorbMesh> > meshList;
vector<boost::shared_ptr<AbsorbMesh> > absorbList;
boost::shared_ptr<AbsorbMesh> nurb = new AbsorbMesh(nurbs.CreateMesh(uStride, vStride));
meshList.push_back(nurb);
absorbList.push_back(nurb);
...
...
if (absorbList.size() > 0)
{
float receivedPower = absorbList[0].get()->receivedPower;
}
You are storing the address of an object allocated on stack. The nurbsMesh object gets destroyed as soon as your method which does push_back() ends. If you try to access this pointer afterwards the object is already destroyed and contains garbage. What you need is to retain the object which remains even after the function goes out of scope. To do this allocate the memory for the object from heap using new. But for every new you should have a corresponding delete. But in your case you'll have problems deleting it as you are pushing the same pointer into two vectors. To solve this, you would require some type reference counting mechanism.
Object is deleted when you try get pointer from vector.
Try do
vector.push_back(new Object);
Once you have fixed the problem that others mentioned (storing a pointer to an object that's on the stack), you're going to run into another issue. A vector may reallocate, which results in its contents moving to another location.
The safe way to do this, then, is to store pointers in both vectors. Then, of course, you need to ensure that they get deleted... but that's C++ for you.
absorbList.push_back(&nurbsMesh); is wrong
absorbList save pointer to local object. When nurbMesh is destroyed you can not write
absorbList[0]->
However when I accessed the pointer later on the data seemed to be corrupted
When you put something on a vector, the vector might move it from one physical location to another (especially e.g. when the vector is resized), which invalidates any pointer to that object.
To fix that, you'll need to store a pointer (possibly a 'smart pointer') in both vectors (instead of having one vector contain the object by value).
If you're going to do this, it might be a good idea to disable the object's copy constructor and assignment operator (by declaring them as private, and not defining them) to ensure that after an object is created it cannot be moved.
There are several things wrong with your example
AbsorbMesh nurbsMesh = nurbs.CreateMesh(uStride, vStride);
This object is allocated on the stack. It is a purely local object. This object is going to be destroyed when you reach the end of the current block surrounded by {}.
absorbList.push_back(&nurbsMesh);
Now you get the pointer to the object that most likely will be destroyed.
meshList.push_back(nurbsMesh)
And this copies an entirely new object on the vector.
It is equally wrong to push the object on the vector first and then push a pointer to the object on the vector using absorbList.push_back( &meshList.back() ) because vector::push_back will reallocate the whole vector, invalidating all pointers.
You might be able to create all AbsorbMesh objects first, push them onto a vector, and then get the pointers to these objects in the vector. As long as you don't touch the vector, you'll be fine.
Alternatively, create objects on the heap using new AbsorbMesh() but make sure to call delete on each pointer thus created. Otherwise you have a memory leak.
Third solution, avoid the trouble and use smart pointers that take care of object destruction for you.
First, as everybody else points out, you can't allocate objects on the stack (i.e., other than by new or something similar), and have them around after leaving the scope.
Second, having objects in an STL container and maintaining pointers to them is tricky, since containers can move things around. It's usually a bad idea.
Third, auto_ptr<> simply doesn't work in STL containers, since auto_ptrs can't be copied.
Pointers to independently allocated objects work, but deleting them at the right time is tricky.
What will probably work best is shared_ptr<>. Make each vector a vector<shared_ptr<AbsorbMesh> >, allocate through new, and at a slight cost in performance you avoid a whole lot of hassle.