is it right to use the new operator like this? - c++

int main()
{
int* nir = new int; // creating dynamic memory
*nir = 7; // assigning value
cout << *nir << endl;
delete nir; // deleting
nir = 0; // **is this line for assigning the address nir=0? 0 is also part of memory right? Why didn't we put NULL?
*nir = 8; // **can i do like this and change the value, so that the output can be 8 now?
cout << *nir << endl;
delete nir;
nir = 0;
return 0;
}
This is the code that I created to understand new. But, even though it was compiled fine by Code::Blocks, during the runtime, it crashes. I have two questions, which I have already mentioned in comment part.
nir = 0;
is this line for assigning the address nir = 0? 0 is also part of memory right? Why didn't we put nir = NULL?
*nir = 8;
can I do like this and change the value, so that the output can be 8 now? After all, I have already deleted the *nir value.

nir=0;
This sets the pointer to NULL. 0 and NULL are the same in this context.
*nir=8
This is wrong as nir in not a valid pointer. It's no suprise that it crashes!
cout<<*nir<<endl;
This is also wrong as nir is invalid pointer. You cannot read or write.
delete nir;
This is harmless, as deleting a NULL pointer is safe (it does nothing).

This code snippet is wrong
nir=0; //**is this line for assigning the address nir=0? 0 is also part of memory right? Why didn't we put NULL?
*nir=8; //**can i do like this and change the value, so that the output can be 8 now?
cout<<*nir<<endl;
delete nir;
nir=0;
You did not allocate memory and are trying to write to address 0.
*nir=8; //**can i do like this and change the value, so that the output can be 8 now?
Usually the program will crash.
As for the line
nir = 0;
then it is equivalent to
nir = NULL;
In C++ NULL usualy defined as 0 or ( long )0 and so on.
According to the C++ Standard
1 A null pointer constant is an integer literal (2.14.2) with value
zero or a prvalue of type std::nullptr_t. A null pointer constant can
be converted to a pointer type; the result is the null pointer value
of that type and is distinguishable from every other value of object
pointer or function pointer type.

You tagged c++ so I recommend using nullptr instead of 0/NULL
nir = nullptr;
The problem
The literal 0 (which is essentially of type int) also serves as a null pointer literal in C++. This kludge results in ambiguity and bugs.
Solution
Use the nullptr keyword instead of 0 to indicate a null pointer value
source

A short breakdown of errors you purposely committed:
int main()
{
int* nir = new int; // allocating dynamic memory
*nir = 7; // assigning value
cout << *nir << endl;
delete nir; // deleting
nir = 0; // **is this line for assigning the address nir=0?
// 0 is also part of memory right? Why didn't we put NULL?
The previous comment is wrong. For historical reasons, assigning a literal 0 to a pointer variable means setting it to a null pointer constant. This is not guaranteed to be 0 [!!!]. NULL and nullptr_t are more modern...
*nir = 8; // **can i do like this and change the value,
// so that the output can be 8 now?
cout << *nir << endl;
On some systems you can do that. But your computing platform is now irretrievably corrupted. Modern systems catch the culprit and raise General Protection Fault, which only kills your program.
delete nir;
Because programmers are keen to avoid useless work, the above (delete NULL) is defined as a no-op
nir = 0;
return 0;
The previous two lines are useless, as nir is never used again and main per standard returns 0 unless it explicitly doesn't, quite in contrast to any other function.
}

Related

How is it possible that a null pointer still retains a memory adress?

When you initialize a pointer with nothing(NULL), that element still has a memory address big enough for the initialising type of that pointer(4 bytes for int, 1 for char etc.) but why,since it's tehnically nothing, not even the value zero? I mean, NULL can't be a fixed value like 0 because zero still is considered a value, so it is something more than that?
Example:
#include <iostream>
int *a=NULL;
int main()
{
std::cout <<&a; //it will show the address in hexadecimal system;
return 0;
}
Your program does not answer the question you were asking. This program shows that, yes the pointer has an address, it needs one to store the value (the address it is pointing to). When you print the value you see that it is indeed nullptr (since this is C++ not C).
#include <iostream>
int *a= nullptr;
int main()
{
std::cout << &a << '\n'; // Will show the address OF THE POINTER in hexadecimal system;
std::cout << a << '\n'; // Will show the address at a is pointing to.
return 0;
}
Output:
0x601180
0
I'm pretty sure there's a duplicate, but I don't see any now. You confuse the meaning of operators * and & in different contexts.
Here, &p means "address of p". And what is p? p is a global variable of pointer type. It is perfectly valid to take address of any global variable.
So, to clear things up:
#include <iostream>
int *a=NULL;
int main()
{
std::cout << &a; //perfectly valid, address of p, type int** (pointer-to-pointer-to-int)
std::cout << a; //still valid, it gives address to where p is pointing, i.e. 0 (NULL)
std::cout << *a; //wrong, dereferencing an invalid address, there's no memory allocated
return 0;
}
You also seem to have few misconceptions about pointers:
"that element still has a memory address big enough for the initialising type of that pointer(4 bytes for int, 1 for char etc.)"
Not at all. Pointer is just a pointer. It doesn't care where does it point to. In fact, on lower levels it's just plain int. It can point to an array, to an element, to nothing at all or to some wild place where nothing was ever stored.
"NULL can't be a fixed value like 0 because zero still is considered a value, so it is something more than that?"
Again, pointer is just a pointer. Pointer doesn't know anything at all about value. Value may or may not exist, and the memory where pointer points to may or may not be valid. And in fact, NULL is defined to be exactly 0 (or nullptr in newer standards): https://en.cppreference.com/w/cpp/types/NULL

How to check if a pointer still points to valid memory in C++?

I have a pointer which equals to another pointer
I'd like to check if my pointer equals to a pointer which is not null.
int* ptr0 = new int(5);
int* ptr1 = ptr0;
delete ptr0;
if ( ?? )
{
std::cout << "ptr1 equals to a null ptr" << std::endl;
}
What should I write in the condition ?
Knowing that:
I don't want to set nullptr any of the ptr's after removal
I don't have access to ptr0 in my condition
Use a shared_ptr<T> combined with a weak_ptr<T>.
For example,
int main() {
std::tr1::shared_ptr<int> ptr0(new int);
std::tr1::weak_ptr<int> ptr1_weak(ptr0);
*ptr0 = 50;
// Depending on if you reset or not the code below will execute
//ptr0.reset();
if (std::tr1::shared_ptr<int> ptr1 = ptr1_weak.lock()) {
std::cout << "Changing value!" << std::endl;
*ptr1 = 500;
}
}
You can't. While in theory you could, depending on the implementation of new, check if the memory pointed to is currently in use there's no way to confirm that it's still the same object you were originally pointing to using only raw pointers.
You can use C++11 smart pointers to do something kinda like that, but I really don't think that's what you actually wanna do here.
delete does not result in a null pointer. It results in a dangling pointer, which is undetectable in general. So, you cannot.

De-allocating memory within loops

I was reading through MIT's Introduction to C++ and one code example showed:
int *getPtrToFive() {
int *x = new int;
*x = 5;
return x;
}
int main() {
int *p;
for (int i = 0; i < 3; ++i) {
p = getPtrToFive();
cout << *p << endl;
delete p;
}
}
I was wondering why it is possible to delete "p" after every iteration despite "p" being declared once before the loop started and was not allocated using "new".
Another question is when "*x" is assigned the value 5 in the function, since it is a pointer the memory address would be changed right? So it would be something like 0x00005 instead of the actual value 5?
I was wondering why it is possible to delete "p" after every iteration despite "p" being declared once before the loop started and was not allocated using "new"
No. You are not deleting p, you are deleting the object p points to, which is allocated using new each iteration.
Another question is when "*x" is assigned the value 5 in the function, since it is a pointer the memory address would be changed right? So it would be something like 0x00005 instead of the actual value 5?
The value of x would be something like 0xFFd00whatever. but you are printing the value of *x, which is "the number that is in the memory at address 0xFFd00whatever". There is no x=5 in your code; there's only *x=5. It means "go to the address to which x points to, and put the number 5 in there".
You can think about it this way: you have a hand, okay? let's call it "x". The command
x = new int;
Means "point your finger at some empty place on your desk." Where
*x = 5;
Means "draw the number five where your hand points to".
p is simply a variable of the type int* (pointer to int). Its value is an address. When you assign a new value to it then it points to a new object. delete expects an address; that's all it needs to deallocate the memory you allocated.
The variable used to store said address is irrelevant. It's value has changed, and that's all delete cares about; the value.

Operator precedence and pointer arithmetic

Given the following code:
void Allocate(int *p)
{
p = new int;
*p++ = 2;
}
int main()
{
int i = 10;
Allocate(&i);
std::cout << i << std::endl;
}
I'm a bit confised about the meaning of:
*p++ = 2;
The output is 10 and my reasoning as to why this is the case is that *p++ is a temporary therefore any assignment to it is lost at the end of the scope of Allocate(int *p).
Is this the case?
Thanks in adv!
On input to Allocate, p points to the variable i in the main
function.
The address of this variable then lost and replaced by the
new int.
The value of this int (which is uninitialized and so could
start as anything) is set to 2.
The p pointer is incremented.
The Allocate function returns at this point, leaking the int that was
allocated.
The value of i in the main function is unchanged,
because Allocate did not modify it.
when you pass the the address of i into Allocate, another (temp) pointer is created that points to i's address (i.e. passing by pointer). then that temp pointer is pointed to a new location (via new int). thus the value of i is left alone.
p = new int;
You're assigning p new memory to point to instead of what it was pointing to before. You then change this newly allocated memory and it's lost forever when the function ends, causing a memory leak. If you remove the allocation line, it should cause an output of 2. The ++ does nothing in this case. It just increments the pointer and returns the old value to dereference.
As soon as you enter Allocate, you assign p to point to a new block of memory, so it no longer points to i. Then you modify that new block of memory (which is then leaked when the method returns.) i is unaffected because you've moved that pointer before you set the pointed-to memory cell.
void Allocate(int **p)
{
*p = new int;
**p = 2;
}
int main()
{
int j = 10;
int *i = &j;
std::cout << i << std::endl;
Allocate(&i);
std::cout << i << std::endl;
}
Output is :
10
2
You need a pointer to pointer to change the address of the location being pointed to.

Confused: Pointers to Dynamic Arrays Syntax

int* p_bob = new int;
*p_bob = 78;
The above code makes sense to me. I use the de-reference operation to allocation new memory and assign a value of 78.
int* p_dynint = new int[10];
*p_dynint[2] = 12;
This however doesn't make sense. If I try to use the de-reference operator on p_dynint[] I get an error. Why would an array be any different?
*p_bob = 78; this assigns the value 78 to the memory pointed to by p_bob (which represents an int).
p_dynint[2] = 12; simply accesses the 3rd element.
p_dynint[2] is actually equivalent to *(p_dynint+2).
p_dynint[2] is equivalent to *(p_dynint + 2). The derefencing is implied in the [] operator.
It is no real problem to do this:
int* p_dynint=new int[10];
//write first element
*p_dynint=10;
//write second element
*(p_dynint+1)=20;
//write three elements to std::cout
std::cout<<p_dynint[0]<<p_dynint[1]<<p_dynint[10]<<std::endl;
This example also highlights a problem with arrays. You can read and write anything. The output generated by p_dynint[10] is an int but its value is just the next few bytes converted to an int.
Use containers if possible (for further reasoning read this)