Lets say I have a node struct defined as below :
struct Node
{
int data;
Node* left;
Node* right;
}
lets say i have a node Node abc and xyz and :
abc->data = 1;
abc->right=NULL;
abc->left=xyz;
xyz->data =2;
xyz->right=NULL;
xyz->left=NULL;
Later if i want to delete the node xyz, is it the same if i say:
delete xyz
vs. saying:
xyz=NULL;
Could someone explain the difference or point me in the right direction ?
No, it is not the same. delete X; statement actually calls a destructor of the object pointed by X and releases/frees the memory previously allocated for that object by operator new.
The X = NULL; statement simply assigns addres 0x0 to the pointer X and neither destroys the object pointed by X nor releases the memory as opposed to delete.
delete frees the memory, but does not clear the pointer.
setting the xyz to NULL just clear the pointer, but does not free the memory.
This is one of the many differences between C++ and Java/C#/JavaScript in its memory management -- in systems with Garbage collection the clearing of a reference/pointer such as xyz above will allow the garbage collector to later free the memory. C++ (or C) does not have garbage collection which is why memory must be managed as part of the program or otherwise you will end up with memory leaks.
As Vlad Lazarenko wrote above, these operations are not the same. In real code you should use smart pointers and do not call delete operator directly.
boost::shared_ptr<std::string> x = boost::make_shared<std::string>("hello, world!");
x->size(); // you can call methods of std::string through smart pointer
x.get(); // and you always can get raw pointer to std::string
Modern compilers allows you to write less code:
auto x = std::make_shared<std::string>("hello, world!");
Related
If we have a function like this:
int* foo()
{
int *x;
x = new int;
delete x;
return x;
}
We need to return a pointer in a function, but what we have learned is we need to delete a space in the final.
If we delete x first as above, then is it meaningful to return x in the final line? Because the x does not exist anymore.
But if we don't delete x before return, the function will be finished.
How can we do?
Or we don't really need to delete a space which was allocated in the memory?
You do need to delete the pointer at some stage, but that does not have to be in the same function scope where you new it. It can happen outside of your function, which I think is what you're trying to achieve.
int* foo()
{
int *x;
x = new int;
return x;
}
int *px = foo();
// use px in some way
delete px;
if we delete x first as above, then is it meaningful to return x in
the final line? because the x does not exist anymore.
Two things here, first no it is not meaningful to return x after delete x; and secondly, deleting x won't delete the x itself, it will only free up the memory to which the x points to.
or we don't really need to delete a space which was allocated in the
memory?
Wrong. You need to free up every dynamically allocated memory location.
but if we don't delete x before return, the function will be finished.
how can we do ?
What you can do is declare the pointer outside the function and then after you have returned the pointer x from the function, then you can delete it anywhere outside that function which returned the pointer.
Tip:
Consider using Smart Pointers because along with other benefits, one of the biggest benefit of using Smart Pointers is that they free up the allocated memory automatically and save you the headache of freeing up the memory explicitly.
There is absolutely no reason at all to delete the pointer before returning it. The only thing you will get is the memory address to a piece of memory that was allocated but no longer is.
It would make sense in this code:
main()
{
int *ptr = foo()
cout << "The memory address that function foo got "
<< "allocated to a local pointer is " << ptr << endl;
}
But come on, who would ever want to write such a thing?
It is, however perfectly ok to delete after the function call, like so:
int* ptr = foo();
delete ptr;
What you need to understand is that delete does not remove a pointer. What it does is to say "I (the program) am done with whatever this pointer is pointing to. You (the os kernel) can use it for anything now. I will not do anything more with that address. I promise." to the operating system. You do not have to have one delete for every pointer. This is completely ok, and causes no memory leaks:
int *p=new int;
int *a[3]={p, p, p};
int n;
cout << "Via which pointer in array a do you "
<< "want to delete the allocated memory? ";
cin >> n;
delete a[n];
It is pretty silly code, but it shows my point. It is not about the pointer. It's about what the pointer is pointing at.
And remember one thing. A pointer does not get the value NULL when you delete it. You have to take care of that separately.
Variables declared in the scope (between the {} ) of the functions are distroyed when leaving the function, as they are built on the stack memory of the function.
When using new(), memory is allocated on the heap, another memory space independant from the function.
This memory won't be freed before you delete the pointer pointing this memory, that's why once using a new(), you'll have to get the pointer deleted before your app returns.
Returning a deleted pointer doesn't make sense unless you want your application to crash. Dereferencing (accessing) a deleted pointer can lead to application crash or memory corruption.
If the purpose of your function is to provide a valid pointer on some type,
the delete will have to occur outside of the function, once you wont need to use the variable anymore.
Two last tips:
don't delete a pointer twice, this would cause a crash.
assigning 0 to a deleted (or non allocated) pointer can be a guard:
ex:
int * pt = 0;
pt = new int;
*pt = 12;
delete pt;
pt=0;
if (pt==0) {
// the pointer doesn't point to anything, and we can test it safely
}
/* ... */
if (pt!=0) {
delete pt; //this second delete wont occur if pt is null (==0)
pt=0;
}
I'm new to C++ and I found out that I have been spoiled by Java and newer programing languages like Swift. So I understand that sometimes you have to delete objects manually in C++ such as pointers. You can use the delete keyword or you can use the smart pointers. But I'm confused on whether that deletes the pointer itself, so the pointer can't be pointed again or if it deletes where the pointer is pointing.
I'm writing code that acts as a integer linked list. So I have a pointer pointing to the head and the tail of the list. When ever someone 'polls' something it should delete it from the list and then reset the head (or tail) accordingly. So I have some code that works fine for what I need it to do:
int IntegerLinkedList::pollFirst(){
if (tail == nullptr && head == nullptr) {
return 0;
} else if (head == tail) {
int ret = head->getData();
head = nullptr;
tail = nullptr;
//delete head;
//delete tail;
return ret;
} else {
IntegerNode* newHead = head->getNext();
head->setNext(nullptr);
newHead->setPrevious(nullptr);
int ret = head->getData();
//delete head;
head = newHead;
return ret;
}
}
But I never really delete the object that it was pointing at, I just remove all the pointers to it. Does that delete the object like it would in Java? Or do I have to manually delete it and how would I do that? Am I memory leaking??? Thanks so much
Also the code that updates the head is
void IntegerLinkedList::addFirst(int x){
IntegerNode* n = new IntegerNode(x);
if (head == nullptr && tail == nullptr) {
head = n;
tail = n;
} else {
head->setPrevious(n);
n->setNext(head);
head = n;
}
}
And the head was defined in the header as
IntegerNode* head;
Java has a garbage collector that essentially does what smart pointers do. That is, when the last reference to an object falls out of scope clean up the memory.
The delete keyword frees up the memory at a location the pointer points to. It doesn't actually do anything to the pointer variable itself (which is just an address).
The way to correct your code would be:
else if (head == tail) { // suppose head = 0xAD4C0080
int ret = head->getData();
delete tail; // cleans memory at 0xAD4C0080, head and tail are still 0xAD4C0080
head = nullptr; // now head = 0
tail = nullptr; // now tail = 0
return ret;
} else {
IntegerNode* newHead = head->getNext();
head->setNext(nullptr);
newHead->setPrevious(nullptr);
int ret = head->getData(); // obtain data while head still exists
delete head; // get rid of head
head = newHead; // remove stray reference to deleted memory
return ret;
}
If you attempted to use the value 0xAD4C0080 after calling delete in these examples you would get a segmentation fault.
As for smart pointers (quoting from your comment):
yes the smart pointers, but do they delete what it is pointing at or just themselves
Smart pointers delete what they are pointing to when they themselves get deconstructed (usually by falling out of scope). i.e.
void func() {
std::unique_ptr<int> pInt(new int);
} // pInt falls out of scope, std::unique_ptr<int>::~std::unique_ptr<int>() called
I'm confused on whether that deletes the pointer itself, so the
pointer can't be pointed again or if it deletes where the pointer is
pointing.
It deletes what the pointer is pointing to. The pointer must be pointing to an object that was allocated with dynamic scope (the new keyword).
I just remove all the pointers to it. Does that delete the object like
it would in Java?
Of course not.
Or do I have to manually delete it and how would I do that? Am I
memory leaking???
You have to manually delete it, using the delete keyword, and, yes, you are leaking memory unless you do that.
It is often said that it's easier to learn C++ from scratch, than to try to learn C++ if you already know Java. C++ objects work fundamentally differently than they work in Java.
And not only differently, but in ways that have no equivalent in Java, at all. There is no Java equivalent, for example, of an object instantiated in automatic scope, in C++.
The full explanation of various scopes of C++ class instances cannot be fully given in a brief answer on stackoverflow.com. You need to get a good book on C++, and start reading it.
And forget everything you know about classes from Java. C++ classes don't work that way. The longer you keep trying to draw analogies with Java, the longer it will take you to learn how to use C++ classes correctly.
Yes, some of the pain can be helped by using smart pointers, which will take care of some of the pain points. But understanding smart pointers in of themselves also requires complete understanding of C++'s class model. Smart pointers do not solve everything, and it is important to understand how C++ classes work, in order to understand what problems smart pointers do solve, and what problems they do not solve.
It depends on what the type is for head and tail. In C++, there are operators (e.g., operator=), and there are destructors. This can lead to certain interesting consequences. Take this example:
#include <memory>
int main() {
// allocate memory
int* ptr = new int;
// store in smart pointer
std::unique_ptr<int> smart_ptr(ptr);
// create another wrapped pointer
std::unique_ptr<int> smart_ptr2(new int);
// throw away location of allocated memory
ptr = nullptr;
// free memory by assigning to smart pointer
smart_ptr = nullptr;
// we can call delete safely here because ptr is null
delete ptr;
// data pointed to by smart_ptr2 will
// be deleted at end of scope
return 0;
}
Additionally, there are two operators for allocating memory, operator new and operator new[], which must be free'd using delete and delete[] respectively.
A more detailed explanation of these concepts may be beyond the scope of this site.
Am I memory leaking???
Yes, if you new something, you must delete somewhere. Assigning pointer to nullptr won't ever affect the allocated data.
But I'm confused on whether that deletes the pointer itself, so the pointer can't be pointed again or if it deletes where the pointer is pointing.
The delete keyword will delete the content at the address you send to it. It won't delete named variable, as variable on the stack are destructed at the end of the scope. Deleteting manually something with automatic storage led to undefined behaviour.
I see you are confused about std::unique_ptr No, they are not deleting themselves. Like any other variable, thier destructor are called and the variable is destructed. The thing about std::unique_ptr is that in their destructor, they delete the data they point to, with you having to delete it yourself. You should read about the RAII idom.
There's a thing about your code, these lines in particular:
head = nullptr;
tail = nullptr;
delete head;
delete tail;
This won't do a thing. You are deleting no data, as head and tail point to nothing. Since the delete keyword deletes the data pointer are pointing to, it won't delete anything.
However, take this example with std::unique_ptr:
{
std::unique_ptr<int> myPtr;
myPtr = std::make_unique<int>(); // or you can use `new int;`
myPtr = nullptr; // The old int you allocated with `std::make_unique` is deleted.
myPtr = std::make_unique<int>(); // assign a newly allocated int
}
// Here, myPtr will free his data as it leaves the scope.
If you use the new keyword, then you always need to use delete. Memory allocated using new is not managed.
Currently your program is leaking memory in the pollFirst method, because you do not free the memory that head and tail point to before re-assigning them. You can do this by calling delete head and delete tail before re-assignment.
You should look into using one of the smart pointer types, such as unique_ptr, if you want automatic management of the memory your pointers point to.
There are few things you should know about C++.
Destructor (DTOR) : Destructor is something which you define for your class. If you don't define a destructor of your own compiler does it for you.
When you call delete for a pointer the DTOR of that class is called which does the necessary cleanup. In order to test it, please put a breakpoint to the DTOR and run the code. Once the control hits DTOR, check the call stack, you will find out that last frame below the DTOR in call stack is the line where you call delete.
As far as the smart pointers are concerned, it does something similar to the garabage collector. Smart pointers have something called reference count. The moment reference count of a smart pointer goes to 0, the DTOR is called.
NOTE: It is advised to write your own DTOR if you have a data member in the class which is pointer.
I was implementing a LinkedList using C++, and I seem to have forgotten a few things when dealing with dynamically allocated memory.
I have a node class:
class Node {
public:
Node(int d) {
data = d;
next = NULL;
}
Node(int d, Node* n) {
data = d;
next = n;
}
int data;
Node* next;
};
and in my LinkedList class, I have the following method:
void remove(int n) {
Node* current;
current = head;
Node* previous = NULL;
while ( current->data != n && current->next != NULL) {
previous = current;
current = current->next;
}
if (current->data == n) {
previous->next = current->next;
current->next = NULL;
delete current;
}
else {
std::cout << "Node not found" << std::endl;
}
}
I seem to have forgotten..When I do delete current does that delete the Node ? Like the actual object that the pointer current points to? Or does it just delete the pointer? Or does the deletion of a pointer pointing to dynamically allocated memory using delete delete both the pointer and the object? Or do I need to have defined a Node class destructor for that?
It just deletes the struct -in your case node- it points to, you can still use that pointer -make it point to another node-, in fact there's no way delete the pointer itself since it's allocated on the stack. it's automatically "deleted" when you leave the function.
p.s: no need to set current->next to null
Delete just free's the memory pointed to. This has the following implications:
You are not allowed to access the memory at this location (use after free)
The amount of memory you needed for your Node object is free, meaning your program would use less RAM.
The pointer itself points either to a non-valid location or NULL, if you follow best practise and set it to NULL manually.
The data at the memory location where your object was can be overwritten by any other task that has a valid pointer on this location. So technically the Node data still remains in memory as long as nobody else overwrites it.
delete p causes the object pointed to by p to cease to exist. This means that
1, If the object has a destructor, it is called; and
2. p becomes an invalid pointer, so that any attempt to dereference it is undefined behaviour.
Generally, the memory occupied by said object becomes available to the program again, though this is really an implementation detail.
The phrase "delete the pointer" is normally a sloppy shorthand for "delete the object pointed-to by the pointer".
Assuming that you have allocated your object using new delete on a pointer does the following:
calls the destructor of the object
request that the memory is free ( when that happens is actually implementation dependent )
At some point the memory manager will free and mark it as non-accessible by the process.
Thus it is up to you to set the pointer after calling delete to an agreed value. The best practice it to set it as nullptr for the latest compilers.
It does delete the actual structure pointed to by current. Pointers remain intact. No need for defining destructor.
The delete operator is to be applied to pointer to object. The pointer is an address of memory on heap allocated by calling new. Internally there is just table of addresses allocated by new. So the key to free such memory is just that address. In your case such address is stored in variable of type pointer to Node named current.
There are few problems in your code. The problematic one is that you have no posibility to tell whether node stored in current is actually allocated on heap. It might happen that current node is allocated on stack. E.g.
void someFunction(LinkedList &list) {
Node myLocalNode(10);
list.add(&myLocalNode);
list.remove(10); //<-- disaster happens here
}
The same applies to statically allocated global variables.
You must take care of extreme cases. Think about what happens when deleted object is the first one, pointed by variable head. By deleteing its memory you end up with dangling pointer in head, pointing to either unallocated memory or memory used by someone else.
My third objection is to writing such structure at all. I hope it is just some school excercise, because in any other cases you should (almost must) use some existing list like std::list from C++ STL.
Whenever you call delete on a pointer variable, the object to which it is pointing to gets deleted from the memory, however the 4 bytes allocated to the actual pointer variable (in your case, the current variable), the 4 bytes will be freed only when the variable will go out of scope, ie At the end of the function
my node contains an int and a string variable, and I tried using binary search tree. the code is as follow:
struct node{
int a;
string members[5];
};
int main(){
node * root = NULL;
root = (node*)malloc(sizeof(node));
root->members[0] = "aaaaa";
return 0;
}
of course, my code wasn't exactly like that, I made it short in main because I want to show just the problem. it gave me 'access violation writing location'. I tried using 'new node();' instead of malloc and that didn't happen. why is this exactly?
malloc() only allocates memory. It doesn't call the constructor of the object. You could call the constructor on allocated memory using, e.g.
void* mem = malloc(sizeof(node));
if (mem) {
node* root = new(mem) node;
// ...
}
When using new node instead of malloc(sizeof(node) the allocate memory also gets initialized. Using an uninitialized object is undefined behavior.
malloc only allocates raw storage. new allocates raw storage and initializes it to contain a specified type.
If you're allocating only POD types, that distinction is mostly one of wording, with little real difference in what happens.
If you're allocating something like an std::string that has a constructor, there's a world of difference though. If you use new, then your string variables have all been initialized so they're real (albeit, still empty) strings. When you just use malloc, they haven't been initialized at all--they're just chunks of uninitialized raw storage the right size to contain a string. When you try to use them as a string, a quick crash is about the best you can hope for.
If I remove a pointer to an object, what will be removed? Only the pointer or also the object which the pointer points to?
For example:
Assume I have a class with a variable
int *root
If I do the following in a method of that class
int *current = root;
delete current;
Will root also be deleted or only the pointer current?
I think you have a misconception about what delete does: delete deletes an object pointed to by a pointer that was previously allocated with new:
int* p = new int; // Create a new int and save its address in p
delete p; // Delete the int
Note that this does not delete p itself in any way, but only the object p points to! You can still use p like a normal variable, e.g. reassign it.
When you have multiple pointers to a pointee you only need to call delete on one of them.
int* root = new int;
int* current = root;
delete current;
std::cout << *root; // undefined behavior
The behavior of delete is described in ยง5.3.5:
6 If the value of the operand of the delete-expression is not a null
pointer value, the delete-expression will invoke the destructor (if
any) for the object or the elements of the array being deleted. In the
case of an array, the elements will be destroyed in order of
decreasing address (that is, in reverse order of the completion of
their constructor; see 12.6.2).
Yes, root is deleted, but depending of the compiler, current can still contain the address of an unexisting variable. So you have to do this to avoid mistakes :
delete current;
current = 0;
int *pointer = new int;
After this statement pointer would be pointing( pointer would be containing the address ) to a block of memory enough to store integer. What internally happens is some chunk from free store would be assigned allocated status.
When you execute
delete pointer;
That memory is returned back to free store so as to fulfill future needs. But you pointer would be containing the same address. When you execute delete again , it would led to undefined behavior since that block is already returned to free store ( that means you have lost the control over that memory through this pointer )
So, to be on safe side you generally set pointer to 0 after deleting that memory.
pointer = NULL;
In implementation of operator delete there is code which check if pointer is NULL, if it is then it returns. So, it's said that there's no harm in deleting NULL pointer.
I hope I have covered every basics.