My question is why i need delete and then remove , can't same
operation done in single command ?
There would be 6 answers from me to your question and Let this be your introduction to Pointers , Stack and the Heap.
1.) new
operator "Allocates" memory on the heap not the stack,Create that Object (Using it's Constructors) then return a Pointer to the Object that is now on the Heap, hence the need for using the delete
operator to "De-allocate" the memory you have requested and "Destroy" the created Object.
2.) delete
"De-Allocates" the memory from heap and "Destroy" the created Object, and it does not remove it from the vector
3.)t.pop_back()
will remove the Pointer element from the vector but will not de-allocate and Destroy the object the Pointer is Pointing too.
4.) It can't be done with one line since you have requested to allocate a Memory on the heap that can fit struct T
inside via the new
keyword. By using the keyword new
the vector std::vector t
is not storing an Object struct T
,[std::vector<T>
] instead storing Pointers to an Object of struct T
[std::vector<T*>
] since you did not explicitly Say what the Vector would Hold.
5.) Heap Allocated memory is perpetual , meaning it will always be there and labeled "In Use". Neither the Program, Runtime nor the O.S. can use it to allocate a new Memory Region on the heap unless you explicitly de-allocate and destroy it when using delete
, Essentially saying "I'm done with this memory location thank you You may now destroy this object and re-use the memory)". or the Program Closes / Ends. So every new
or new[]
must be accompanied by delete
or delete[]
somewhere in the code when that variable is no longer in use anywhere in the program.
6.) After you understand the behavior of Heap / Dynamic Variables have a look at Smart Pointers. Which Handles the destruction of an object for you automatically. If you are coming from Managed Languages, you might want to read up on "Object Lifetimes" on C++.
The following Code will help you visualize my answer.
#include <vector>
#include <iostream>
struct T
{
T(int n):x(n){};
int print() {
return x;
};
// Replaces the Value of X
void SetX(int n){x=n;};
private:
int x;
};
int main(int argv,char** argc)
{
// We explicitly Say that the Vector is holding a Pointers to an object struct T
std::vector<T*> t;
// Insert New Elements to the Vector
t.push_back(new T(1));
t.push_back(new T(2));
// Will show that there are 2 elements in the vector.
std::cout << "Size of Vector Is " << t.size() << std::endl << std::endl;
// Assign the Last Element to a Pointer of T.
T* pointerToT = NULL;
pointerToT = t.back();
// Print the Memory Address and value of pointerToT and the Last Element
// And we can see they are the same location and holds the same value.
std::cout << "The Memory Location of pointerToT is " << pointerToT << std::endl;
std::cout << "The Memory Location of t.back() is " << t.back() << std::endl;
std::cout << "The Value of X in pointerToT is " << pointerToT->print() << std::endl;
std::cout << "The Value of X in t.back() is " << t.back()->print() <<std::endl << std::endl;
//Removes the Last Element of the Vector
t.pop_back();
// Will show that there is only 1 element in the vector.
std::cout << "Size of Vector Is " << t.size() << std::endl << std::endl;
// Print the Memory Address of pointerToT and the Value of X
// And as we can see pointerToT is still holding the same location
// and still holding the value 2, since the program knows that
// The memory Location is "Still" in use and not yet De-Allocated
// ready to be re-used and the object not yet destroyed.
std::cout << "The Value of X after pop_back() is " << pointerToT->print() << std::endl;
std::cout << "The Memory Location of pointerToT after pop_back is " << pointerToT << std::endl << std::endl;
//De-Allocate the Memory and Destroy the Object that was created by t.push_back(new T(2));
delete pointerToT;
// Prints the value of X, that is stored in the memory on the heap that it's pointing to.
// This Value may or may not be 2 if it is now used other parts of the Code
// which we call an Undefined Behaviour.
// On a Larger Program this could and would Cause a Segmentation fault or
// an Access Violation since this is now a Memory Region that is not explicitly
// Allocated for pointerToT , to the Member Variable X, nor
// The Last Element of the Vector and may now be in use by other variables and that the object is Destroyed already destroyed.
std::cout << "The Memory Location of pointerToT after delete is " << pointerToT << std::endl;
std::cout << "The Value of X after Delete is " << pointerToT->print() << std::endl;
// This is also an undefined Behaviour since you are now accessing and modifying
// a Memory Location that is not Allocated for pointerToT . But would show
// that the value of X is now 10. So only delete(Destroy)when you are sure you are not going to be
// accessing that variable again.
pointerToT->SetX(10);
std::cout << "The Value of X after SetX() is " << pointerToT->print() << std::endl;
return 0;
}