Initialize a pointer to an object - c++

Given an object, e.g. listNode.
If I initialize a pointer to an object with:
listNode* head_node;
How is this any different from
listNode* head_node = NULL;

In the first case listNode* head_node; the compiler will allocate some memory to hold the pointer. That memory can contain any value (for example it could be some random value from when that location was used for something else) and, in fact, reading it will result in undefined behavior.
In the second case listNode* head_node = NULL;, the compiler will allocate some memory to hold the pointer and then write NULL to that location so the pointer is guaranteed to be NULL.
One thing to note, you should use nullptr as opposed to NULL. See this answer for why.

In the first case, you are declaring a pointer variable. In the second case, you are declaring a pointer variable and initializing it to NULL. Any variable that is declared but not initialized leads to undefined behaviour when you try to access the variable. This has nothing to do specifically with pointers, pointers are just like any other variable. For example, if you write int a; and then you cout << a; you will see that a most likely has a random integer value written in it. But if you write int a = 0; and then you cout << a; you will see that a is always 0 on any compiler on any machine. This is well defined behaviour as opposed to undefined behaviour.
I would discourage the use of raw pointers in your case, as you most likely want always them to be initialized to nullptr, plus your listNode is most likely "owned" by the list itself. Try to use std::unique_ptr<listNode> instead: it will both initialize you pointer to nullptr by default and release the allocated memory when the pointer goes out of scope, meaning that if the head of the list will be deleted, all the other nodes in the list will automatically be deleted as well.

Related

Why need to set rvalue reference to null in move constructor?

I've read the post: Why do we need to set rvalue reference to null in move constructor?
It said that during a move, you just copied the pointer from one object to another, so two pointers points to the temporary object. And when the temporary object goes out of scope, its destructor will run. And then the object pointed by 2 pointers would be deallocates. So the pointer field of object constructed by move constructor would point to unavailable place.
However, look at following code:
int *p = new int(3);
int *q = p;
delete p;
std::cout << *q << std::endl;
after delete the pointer p, pointer q could still access the int object.
So, is that just because when the object is accessed by rvalue reference causes the difference?
No you can't. It appears to work, but it's entirely undefined behavior. The memory is released to the runtime.
When you move something, you're effectively saying the original object is no longer valid - you only access its original contents from the moved-to object. Furthermore, the set to NULL after a move prevents a double-delete - when the original objects goes out of scope and attempts to free that memory, it will either fail straight away (if the new object already free'd it) or the new object will fail when it itself attempts to release that memory.
Accessing deleted memory of the free store is undefined behavior.
On move construction, the pointer of the object constructed is set to the pointer of the rvalue, which in turn is set to nullptr afterwards.
The object referenced by the rvalue ends its lifetime thereafter, after all it is a temporary. Therefore, the pointer set to nullptr is not expected to be used anymore. When it is destructed, delete nullptr; is executed, i.e., a no-op.
OTOH, when the lifetime of the constructed object ends, the actual resource is deleted - the pointer to it was assigned in the move constructor.
No, after delete the pointer p, pointer q cannot still access the int object. If you think otherwise because you ran it and got 3 in the output--that's because you caused undefined behavior and UB can "work" as one of its many, many options.
In general what happens is that the memory address hasn't been reused yet, still belongs to the program (so it has permission to access and the value has not been erased), so you'll see whatever value was deleted in that memory. All this means that it will appear as if the code is perfectly OK when it's not. You could also print using *p in this case and it would be no different. The p and q variables both contain the same address...which was freed by a delete.
One interesting aspect of this is that high security applications, or encryption applications like GPG, manually fill deleted memory with garbage so that it can't just be sniffed out--giving access to private keys out to the world. Otherwise the key would still just be written in RAM until someone writes something else there!
This is the problem with pointers. They do not convey ownership semantics.
You should be using something like std::unique_ptr. When you move the pointer from one object to another the old object recognizes it no longer owns the object and thus you can;t access the data.
Simple solution. Like the rest of the C++ community stop using pointers like this.
std::unqieu_ptr<int> p(new int(3));
std::unique_ptr<int> q = p; // Fails to compile
std::unqieu_ptr<int> p(new int(3));
std::unique_ptr<int> q = std::move(p); // explicitly transfer ownership.
// delete p; // No longer need this as when the onbject goes out of scope
// it is deleted.
Both the question you linked and your question is trying to avoid undefined behavior upon dereferencing of q.
The thing is that, (in the linked question) you have to know that you can't dereference q anymore (you aren't managing it) by setting it to nullptr. But here, it's your business to not to dereference q after the delete. It's extremely predictable that q will be deleted before std::cout << *q << std::endl;. It's your fault that you're dereferencing it!
Nevertheless, setting q to nullptr helps with debugging, delete q is no longer UB, and nullptr signifies a pointer to non-existent object.

What will get removed if i remove a pointer in c++

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.

Null pointers in C++

I've got a couple of questions regarding pointers. First:
ObjectType *p;
p->writeSomething();
Why is it possible to call a method on an object when the pointer hasn't been initialized? If I run that code I get the output from "writeSomething()" in my console window. Second:
ObjectType *p;
if(p==NULL)
cout<<"Null pointer";//This is printed out
p = new ObjectType;
delete p;
if(p==NULL)
cout<<"Null pointer";
else
cout<<"Pointer is not null";//This is printed out
Why isn't the pointer null in the second if statement and how do I check if a pointer isn't pointing to any memory address? I'm also wondering if there is any way to check if some memory hasn't been released when a program is done executing. For example, if you forget to write 1 delete statement in the code.
The first code is undefined behavior, anything can happen, even appearing to work. It's probably working because the call is resolved statically, and you're not accessing any members of the class.
For the second snippet delete doesn't set the pointer to NULL, it just releases the memory. The pointer is now dangling, as it points to memory you no longer own.
Your code does of course exhibit undefined behaviour, but here's an example of why it may appear possible to call a member function even if there is no object: If the member function doesn't refer to any member objects of the class, then it will never need to access any part of the memory which you haven't initialized. That means, your member function is essentially static.
As you know, member functions can be considered as normal, free functions which have an implicit instance object reference argument. For example, a simple class Foo defined like this,
struct Foo
{
void bar() { std::cout << "Hello\n"; }
};
could be implemented as a single, free function:
void __Foo_bar(Foo * this)
{
std::cout << "Hello\n";
}
Now when you say Foo * p; p->bar();, this amounts to a free function call __Foo_bar(p);. You end up passing an invalid pointer to the function, but since the function never makes use of the pointer, no harm is done.
On the other hand, if your class had a member object, like int Foo::n;, and if the member function was trying to access it, your implementation would try and access this->n, which would very likely cause an immediate problem since you'd actually be dereferencing an invalid pointer.
delete p;
deallocates memory, but it does not change the value of the address stored in p.
There is no method in standard C++ to detect that a pointer is referring to invalid memory. It is your responsibility not to de-reference an invalid pointer.
Your first example is undefined behaviour. One of the possible outcomes of undefined behaviour is that the program works the way you intended it to. Again, it is your responsibility not to write programs with undefined behaviour.
In your code, writeSomething() is probably a non-virtual member function that does not de-reference this which is why it happens to work for you, on your compiler. Most likely if you tried to refer to some member data fields then you would encounter a runtime error.
delete would call upon the destructor of ObjectType followed by de-allocation of memory but it doesn't explicitly makes your pointer NULL
That is something you have to do as a good programming practice.

Pointer - returning Local reference in C++

I'm not sure if this question has been asked before ( searched through SOF and couldn't find an answer)
I wrote a LinkedList class and a function to reverse it.The function as follows,
struct LinkedList::element* LinkedList::recurrsiveReverseList(element* head){
element* tempList;
if(head->next == NULL){
return head;
}else{
tempList = recurrsiveReverseList(head->next);
head->next->next = head;
head->next = NULL;
return tempList;
}
}
here I am declaring a local pointer variable and making some changes to it and returning it back to the caller. In C++, when I declare a local variable inside a function the scope exists only inside the function. Now when I return the pointer from the function how does it work? I am able to understand the logic and get the result (luckily) but I am not able to completely understand the working here.
Can somebody clear my doubt?
The scope of tempList terminates when you exit the function but tempList is a pointer to a block of memory whose scope does not terminate there because it's been undoubtedly allocated by new. Memory allocated in such a way is valid right up until the point you delete it, regardless of how many functions you go in to or out of.
By passing the pointer back to the caller, it preserves said pointer elsewhere, where you can use it.
A simple example:
static char *fn (void) {
char *rv = new char[42];
return rv;
}
int main (void) {
char *x = fn();
delete [] x;
return 0;
}
In the code above, the scope of rv is limited to the fn function after it's declared.
The scope of x is limited to the main function after it's declared.
However the memory allocated by new comes into existence within fn and continues to exist after returning to main. The address of said memory, initially stored in rv, is transferred to x by the assignment of the fn return value to x.
Not sure if someone else explained it this way, but the pointer itself is nothing more than a number, like... 0x12345678. That number in turn addresses a position in the memory of a computer that contains the actual value you are looking for, which is the linked list node.
So when you return that address, it's okay that the original variable was destroyed. Like copying down a street address to a different piece of paper, then throwing away the original paper. The house that is at the address you have is still there.
The pointer object tempList ceases to exist when you leave the function. But that's ok; you're returning (a copy of) the value that was stored in the object, not the object itself. It's just like
int n = 42;
return n;
(Returning the address of a local variable is what gets you into trouble.)
I assume your linked list nodes are allocated on the free store (i.e. with new).
When you create an object with new, it is created on the free store and exists until you call delete on it. You can make as many pointers to that location as you want, and it exists independent of any function calls it may have been made in. So in this function, you are just returning a pointer by value to that location on the free store. The pointer is just a number which is the address of the object, like returning an int by value.
tl;dr: You obviously know you can return local objects by value because a copy is made. In this function, it returns a copy of the pointer which points to a location on the free store which is only destroyed when delete is called with a pointer to that memory location.
As another note, you probably should not return a pointer to the new head of the list but rather take a pointer to the head of the list by reference and change the list through that, so if someone forgets to assign their old head pointer to the one returned by recurrsiveReverseList, things aren't messed up.
The scope of usage of tempList variable is limited within the method as its local, but it holds a memory address which is what is returned.
The code that call its will receive this memory address, not the variable tempList.

C++ trouble with pointers to objects

I have a class with a vector of pointers to objects. I've introduced some elements on this vector, and on my main file I've managed to print them and add others with no problems. Now I'm trying to remove an element from that vector and check to see if it's not NULL but it is not working.
I'm filling it with on class Test:
Other *a = new Other(1,1);
Other *b = new Other(2,2);
Other *c = new Other(3,3);
v->push_back(a);
v->push_back(b);
v->push_back(c);
And on my main file I have:
Test t;
(...)
Other *pointer = t.vect->at(0);
delete t.vect->at(0);
t.vect->erase(t.vect->begin());
if (pointer == NULL) { cout << "Nothing here.."; } // Never enters here..
Deleting a pointer doesn't have to zero it, it just frees the memory assigned there. Using pointer is undefined after the delete though, as the memory is free to be used for other things. Technically the C++ spec intentionally leaves it up to implementations whether they want to zero a deleted pointer or not, but practically none that I know of do so
The deletion of memory pointed by a pointer, doesn't set the pointer to NULL.
You set pointer equal to the address of something, and never touched it again, so of course it won't be null. The fact that you then did something to the object is irrelevant.
Using simple pointers, there is no safe way for pointer to determine whether the object it once pointed to has been deleted. The simplest way to do what you seem to want to do is by leaving it to the containers: if you're interested in that object, search for pointer in the vector to see whether it's still there (and don't delete the object without erasing the corresponding element from the vector, or you'll have the same problem all over again).
To overcome the checking a deleted ptr problem you could use boost::shared_ptr.
Instead of delete use .reset() and to check if the ptr is still valid use .get()
(Actually you can just use if(p) where p is the shared_ptr because it has a conversion to bool)