What happens when I delete a pointer of pointer? - c++

I have a vector like std::vector<AnyObject*> myVector; and I would like to delete an element in my vector without changing position of my other elements. How can I do this ? I have two solutions, tell me if they are good:
AnyObject* initial;
std::vector<AnyObject*> myVector(10, initial);
AnyObject* object = myVector.at(4);
delete object;
or
AnyObject* initial;
std::vector<AnyObject*> myVector(10, initial);
delete myVector.at(4);
What happens in the first solution when I delete object ? Am I also deleting the pointer in the vector or just the object ?
EDIT :
When I wrote AnyObject* initial;, I know initial isn't initialized, I wanted just say what happens if I a have a vector of initialized pointers and if I wanted delete one pointer without changing position of the other pointers.
EDIT2:
For the context of the problem, I have a class PointCloud and another class SubsampledPointCloud. I want subsampled my all clouds with the same size of the smallest cloud, so among my subsampled point cloud, I have at least one cloud that have the same size of its point cloud. So to build my vector of SubsampledPointCloud, I have a vector of PointCloud initialized, a variable minPointCloudSize equals to the minimum size among my point clouds and I do this :
std::vector<SubsampledPointCloud*> subcloud(clouds.size());
for (std::size_t i = 0; i < clouds.size(); i++) {
if (clouds.at(i).size() > minPointCloudSize)
subcloud.at(i) = subPointCloud(clouds.at(i)); //subPointCloud is a function
//that return a SubsampledPointCloud*
else
subcloud.at(i) = clouds.at(i);
}
and later, I don't need of this subsampled point cloud, so I'm deleting all of this except if the sub cloud with the same size of the original cloud.
Of course, SubsampledPointCloud inherited of PointCloud.

I have two solutions, tell me if they are good
Both of your solutions have UB - you read from uninitialized variable initial. If you manage to put correctly initialized pointers to your vector, then both variants would have the same effect - if fifth pointer in the vector not equal to nullptr, object it points to would be destroyed and memory released. You should understand that delete does not modify argument passed to it, so calling delete would not alter pointer itself and unless it is not equal to nullptr you would have dangling pointer left in the vector. It would be your job to reassign new value to it or to avoid using it after that. Or remove it from the vector calling vector methods.
Am I also deleting the pointer in the vector or just the object ?
You are only deleting object, pointer would have exactly the same value ie point into memory where object used to be.

A segmenation fault in both cases, as you haven't actually created any AnyObjects, only the vector of null pointers.
In general, if you have a vector of pointers to objects, you can delete the object by deleteing the object as you have done, and then setting the pointer to null, to denote that it doesn't point to an object.
To use your example, glossing over the fact you haven't created any objects:
AnyObject* initial;
std::vector<AnyObject*> myVector(10, initial);
delete myVector[4];
myVector[4] = 0;

std::vector<AnyObject*> myVector(10, initial);
This statement will initialize vector with 10 initial object. initial is memory reference and when you delete it that deallocates memory that was allocated for initial object and will make all vector element pointing to invalid memory location in both case. If you will try to access it after delete in both case, the behavior will be undefined.

Your premise is flawed. You shouldn't use raw pointers to handle object lifetimes, use std::unique_ptr (or std::shared_ptr if the lifetime really is shared)
Then your example would look like
std::vector<std::unique_ptr<AnyObject> > myVector(10, nullptr);
// other code
myVector[index] = make_unique<AnyObject>(args...);
// other code
myvector[other_index].reset(nullptr);

Related

Stack vs Heap - Should objects inside *vector be declared as pointers?

If I use this line
std:vector<MyObject>* vec = new std::vector<MyObject>(100);
If I create MyObject's in the stack and add them to the vector, they remain in the stack, right ?
MyObject obj1;
vec->push_back(obj1);
So if it go to the stack, than MyObject's added to the vector will be gone after method ends ? What will I have inside the vector than? Garbage?
Should I use this instead ?:
std:vector<MyObject*>* vec = new std::vector<MyObject*>(100);
And if so, what about objects and primitives inside each MyObject ?
Should they also be dynamically created ?
Thank You
The std:vector as any other Standard Library container copies elements into itself, so it owns them. Thus, if you have a dynamically allocated std::vector the elements that you .push_back() will be copied into the memory managed by the std::vector, thus they will be copied onto the heap.
As a side note, in some cases std::vector may move elements if it is safe to do so, but the effect is the same - in the end, all the elements are under std::vector's jurisdiction.
A std::vector<MyObject> looks something like this (in reality it's much more complex):
struct Vector {
MyObject* data;
int size;
}
As you can see, the data is not directly inside the vector object. The vector always allocates the memory for the data on the heap. Here's what happens when:
you call .push_back: The vector copies the object into its own data block (which is on the heap and owned by the vector)
you copy the vector: The copied vector allocates new memory and copies all data from the existing vector into it
As you can see, the vector owns his data. That means, if you push_back a object into it, it doesn't matter where it came from because it gets copied.
If you have a std::vector<MyObject>* you have a pointer to a vector. This vector also owns his data, but you only have a pointer to it. That means, you have to delete it exactly once, otherwise you'll get a memory leak or a crash. Passing around pointers to a vector is OK, but need one class or function that "owns" it. This class/function has to guarantee that the vector still exists when the pointer to it is used.
The third case is a std::vector<MyObject*>. As every vector, this one also owns his data. But this time, the data is only a pointer. So the vector only owns the pointer, but not the objects to which the pointers are pointing. If you do something like this:
std::vector<MyObject*> getObjects() {
MyObject obj1("foo");
MyObject obj2("bar");
std::vector<MyObject*> vec;
vec.push_back(&obj1);
vec.push_back(&obj2);
return vec;
}
The returned vector only contains garbage because you only saved the address to a object on the stack to it. These objects are destroyed when the function returns, but the pointers in the vector are still pointing to that memory block on the stack.
Additionally, keep in mind that this
std:vector<MyObject*>* vec = new std::vector<MyObject*>(100);
Doesn't store heap allocated objects to the vector. It just stores pointers of type MyObject. If you want to do something like that remember to create the objects first, before you use them. You can do that with something like the following:
for (int i = 0; i < vec->size(); i++) {
vec->at(i) = new MyObject();
}

How is iterator different from a pointer during the deallocation of memory in C++

I have a class "DMRecSessionObj" whose objects are dynamically allocated using new and stored in a map.
static std::map<string,DMRecSessionObj*> mapExpSessData;
DMRecSessionObj* dmRecSessObj = new DMRecSessionObj(atoi(p_callNum),atoi(p_totCalls), sessionKey);
mapExpSessData.insert(std::pair<string,DMRecSessionObj*>(sessionKey,dmRecSessObj));
During the deallocation of memory, I use the below obvious method
delete dmRecSessObj;
dmRecSessObj = NULL; //to prevent it from being a dangling pointer
But I am little bit confused while trying to deallocate the memory using iterator as below:
std::map<std::string,DMRecSessionObj*>::iterator itr_del = mapExpSessData.find(tmp_sessionId);
if (itr_del != mapExpSessData.end()){
mapExpSessData.erase(tmp_sessionId);
delete itr_del->second;
}
In this case, should the iterator itr_del be somehow set to NULL? As normal pointers can result in dangling pointers if not set to NULL, how would the iterator behave in this case? Is anything more need to be done in this case to be safe?
Please suggest.
Thank you.
Once you call mapExpSessData.erase(tmp_sessionId);, the node in the map that itr_del points to has been deleted. Calling delete itr_del->second; is then Undefined Behavior because you try to access deallocated memory.
You need to delete the value in the map first, then delete the node in the map:
delete itr_del->second;
mapExpSessData.erase(itr_del);
The code block the iterator is in should be small at this point, and the iterator itself going out of scope so you shouldn't need to do anything with it to clear it out. But if you really want to you can assign the default value for its type back to it.

Is an object pointer in a vector deleted if I call delete on the object?

Recently, I was confused on why I continuously was faced with a segmentation fault trying to access an element in a vector of pointers of certain objects. I didn't manage to resolve the issue, but I suspect that it is because after I pushed the object pointer into a vector, I called delete on it, thinking that the vector stored a copy.
In the following code:
std::vector<SomeObject *> testvector;
SomeObject * testobject = new SomeObject(/* some arguments here, call constructor */)
testvector.push_back(testobject);
delete testobject; // does this affect the element in the vector?
The debugger confirms that the pointers getting added to the vector do indeed have proper data, but once I call delete on them, I'm unsure if the element inside the vector is affected. Does the vector store just a copy? When I call delete on the object, I suspect that delete is being called on the pointer in the vector, but I am unsure.
Now I tried to print out the data in the vector after calling delete, I get this: ??? ?? ???? ???
And I am assuming that the call to delete has affected the vector element. Is this the case? I thought that after I added the pointer to the vector, I could safely free the object without affecting the element in the vector, but it seems that I end up accessing memory that is no longer allocated. Does the call to delete affect the pointer in the vector?
"Does the call to delete affect the pointer in the vector?"
It doesn't affect the pointer. It affects the behavior invoked by using this pointer since the object it points to no longer exists. When you call delete, the object is deleted and whatever you try to do with that object using invalid (old, dangling) pointer, the behavior is undefined.
std::vector<SomeObject *> testvector;
SomeObject * testobject = new SomeObject()
testvector.push_back(testobject);
Constructs a vector of pointers, creates an instace of SomeObject and pushes an address of this object to your vector. Then when you call:
delete testobject;
There is no way how std::vector could know that the object has been deleted. Your vector still contains an old pointer, which has became invalid by the time the object was deleted. A possible solution could be using a vector of smart pointers such as shared_ptr, however at first you should consider whether you want to use a vector of pointers at first place. Maybe std::vector<SomeObject> would be more reasonable way to go.
The vector contains pointers not the objects theirself. So after deleting an object the corresponding pointer will be invalid.
When you copy a pointer, you only copy the address of the object, not the object itself. That means the pointer in your vector and your pointer outside the vector were still referring to the same thing when you called delete.
The reason the debugger may still have shown seemingly valid data is because the memory doesn't necessarily get overwritten when you delete something. It's simply marked as 'free' so that it can be used by something else later if required.
Yes, both testobject and the inserted element into the vector are pointing to a same address. After deleting one of them another will be a dangling pointer and dereferencing it is undefined behavior.
You can use smart pointers such as std::unique_ptr or std::shared_ptr.
std::vector<std::shared_ptr<SomeObject>> testvector;
std::shared_ptr<SomeObject> testobject(new SomeObject);
testvector.push_back(testobject);
or
std::vector<std::unique_ptr<SomeObject>> testvector;
std::unique_ptr<int> testobject(new SomeObject);
testvector.push_back(std::move(testobject));
// After `std::move` you can not use `testobject` anymore!

Delete pointer allocation after adding it to vector

Once you add an object to a vector in C++, and delete the pointer to that object, will the object inside the vector get deleted too?
for example,
int i = 0;
std::vector<A> aVect;
while(i++ < 10)
{
A *ptrToA = new A();
aVect.push_back(*ptrToA);
delete ptrToA;
}
would it still be valid to call:
aVect.at(2);
Will the call to "delete" destroy the object that was added to the vector, or will it only deallocate the object of the pointer?
Yes you can delete the pointer because, as others have noted you dereference the pointer to it is copied into the vector by value.
It would be more efficient to just construct into the vector like this and avoid new/delete entirely:
int i = 0;
while(i++ < 10)
{
std::vector<A> aVect;
aVect.push_back(A());
}
In C++11 a copy will not be made - the rvalue version of push_back will be used - A will be constructed into it's slot in the vector.
You may not want to create a new vector each time???
std::vector<A> aVect;
int i = 0;
while(i++ < 10)
{
aVect.push_back(A());
}
It will still be valid to call aVect.at(2), since the vector is holding a copy of *ptrToA. When you called aVect.push_back(*ptrToA), it set its A using the assignment operator.
Here you push a copy of the object to the vector and this copy will not get deleted.
However if you write:
int i = 0;
while(i++ < 10)
{
A *ptrToA = new A();
std::vector<*A> aVect;
aVect.push_back(ptrToA);
delete ptrToA;
}
Then you are pushing pointers in the vector and when you delete ptrToA you also delete the element pointed to by the pointer in the vector.
You have created vector of objects of type A: std::vector<A>, which means that when you insert some new object into it, copy of this new object is created and stored into vector.
So yes, it it perfectly safe and valid to access this element even after the new object has been deleted. Deleting the original object won't affect the copy stored in your vector in any way.
Advantage of this kind of vector (vector that holds objects with automatic storage duration) is that memory where these objects are stored is cleaned up automatically once the vector is destructed. So it is less likely that there will be some memory leak in your code as well as less work for you since you don't need to take care of that ugly memory management on your own :)
No it won't. Your std::vector<A> stores instances of objects not pointers. In fact you are dereferencing the pointer while pushing A into the vector.
This will cause a copy of the object (built through copy constructor) to be stored inside your vector. After pushing the object you have 2 instances of an A class. One instance is allocated in the heap (through the new operator). The other instance is on the stack, where aVect is allocated.
On the other hand, if your vector would store pointers (std::vector<*A>), after deleting ptrToA, the pointer stored inside the vector points to an already released memory location (dangling pointer). Trying to access that pointer would cause an error, probably a segfault.

C++, vectors, pointers and objects confusion

I am working on a project as a homework for my university course of Systems Programming.
I got really confused with the matter of Pointers, Vectors, stacks and heaps.
Using C++.
I have to get a vector of objects which are courses, and those courses objects have several different fields.
What I did was this:
vector<CoursesObject> coursevector;
and then I created my Courses Object class, which contains the space left in course and name of course fields.
Now I want to add a new course, I do:
CoursesObject *theCourse = new CoursesObject(name, space);
now I want to add it to the handler vector:
coursevector.push_back(*theCourse);
With all I know, I created a vector of Courses objects on the stack, and made a new pointer to a new course that is on the heap, and added to the handler vector the pointer theCourse that points to the course object in the heap. Is what I said correct?
When I try to delete those course objects, I do:
for(int i=0; i<coursevector.size(); i++)
delete coursevector.at(i);
which gives me an error that it is not a pointer. But haven't I added to the coursevector a POINTER to the course object?
Please somebody explain, I have to handle the memory correctly and it seems that I am not getting it right.
This
vector<CoursesObject> coursevector;
is a vector of CourseObjects, so it cannot hold CourseObject pointers. When you do this:
coursevector.push_back(*theCourse);
you get a copy of the CoursesObject pointed at by theCourse stored in the vector. You do not need to delete any entries from the vector. In fact, you can't, because it doesn't hold pointers.
You program would be much simpler if you just avoided the dynamic allocation:
coursevector.push_back(CoursesObject(name, space));
You do not need to use new at all.
//This vector stores CoursesObject objects,
//not pointers to CoursesObjects.
vector<CoursesObject> coursevector;
//Construct theCourse with automatic storage
//duration.
CoursesObject theCourse(name, space);
//Copy theCourse into coursevector
coursevector.push_back(theCourse);
//theCourse will be automatically destroyed.
//coursevector (and all the objects that it contains)
//will be automatically destroyed.
all of your objects are not dynamically allocated, so you cannot delete them at any time during the program. Remember that you can only delete object once they are dynamically allocated:
int Var1 = 0; //cannot be deleted, scope and life will exist for the life of program
int * Var2 = new int; //CAN be deleted, dynamically allocated.
delete Var2; //free memory
You can however delete your last object, which is a pointer. I would grab the last element of the vector and call delete on it(which should be your pointer to the class).
when you do this:
coursevector.push_back(*theCourse);
actually you are dereferencing the pointer theCourse, so you are adding a copy of the object. You need to declare a vector of CourseObject pointers:
vector<CoursesObject *> coursevector;
Then you add an object:
coursevector.push_back(theCourse);
Now your code to delete the objects should work:
for(int i=0; i<coursevector.size(); i++)
delete coursevector.at(i);
coursevector can hold only CoursesObjects and not pointers to CoursesObjects, so you needn't use the new operator (check #Mankarse's answer). But, if you still want to hold pointers, then change the definition of coursevector to
vector<CoursesObject*> coursevector;
and push_back the value of the pointer as it is:
coursevector.push_back(theCourse);