I'm learning C++ and I have a question about pointers.
I have this code:
int* max = new int;
*max = 0;
I think, I have created a pointer on the heap (if I'm not right, please, tell me).
One question:
Is there a way to create an initialize a pointer with one instruction? (now, I'm using two instructions).
Another question:
How can I create a pointer on the stack?
I see code like this one:
int myVar = 20;
int* pVar = &myVar;
I think I haven't created a pointer on the stack but I think it is the only way to not create a pointer on the heap.
I'm very very very new on C++ development.
int* max = new int;
The above line creates a pointer on the stack and initializes it with an integer stored on the heap. Whenever new is involved in an expression, it will return a pointer to its dynamically-created operand:
Per Paragraph 5.3.4/2 of the C++11 Standard:
Entities created by a new-expression have dynamic storage duration (3.7.4). [ -- ] If the entity is a non-array object, the new-expression returns a pointer to the object created. If it is an array, the new-expression returns a pointer to the initial element of the array.
int myVar = 20;
int* pVar = &myVar;
In this example, both the pointer and its value is stored on the stack. A new-expression was not involved in the assignment, so nothing is created on the heap in this situation.
If you want to initialize the value of the pointed-to object in one line, you'd have to value-initialize it like so:
int* max = new int(5);
or in C++11 you can use uniform-initialization:
int* max = new int{5};
It is also important that you remember to delete that which you created with new. Since the memory is in dynamic allocation, its lifetime is not dependent by the scope in which it was created. If you forget to delete your program will get a memory leak.
delete max;
And if max was a pointer set to an array created by a new-expression, you'd use delete[]:
delete[] max;
Note: If a pointer was not initialized by a new-expression, then there is no need to delete.
It's typically recommended that you use containers to mangage the memory for you. Something like std::unique_ptr will do. Once its destructor is called, the memory it holds is deleted:
std::unique_ptr<int> max{new int{5}};
In C++14 we have make_unique:
auto max = std::make_unique<int>(5);
Pointers are normal variables, which content is a memory address. This memory can be heap memory or stack memory. Don't confuse the pointer with the memory space it points to.
Your first code allocates space on the heap which can hold an int. You store a pointer to that memory on the stack.
Your second code allocates space on the stack which can hold an int. You store a pointer to that memory on the stack.
So both pointers are on the stack, but only the second points to the stack.
In both cases, the type you allocate is a primitive type. Primitive types aren't initialized per default, unless you immediately assign a value to it (your second code), or use the constructor syntax, which also works with heap-allocated values:
int *max = new int(0);
The same syntax can be used in your second code, by the way:
int myVar(20);
In case you're interested: You can also define pointers on the heap. int* is the type of pointers to ints, so just go ahead and allocate such a type on the heap:
new int*();
This expression returns an int**, which you can then store somewhere. Again, you typically store this pointer-to-pointer on the stack:
int **pointerToPointer = new int*();
As with ints, you can initialize an int* in the new-expression to some pointer-to-int (here, the max pointer from above):
int **pointerToPointer = new int*(max);
Now you have two pointers with the same address: max (pointer on the stack) and some pointer on the heap which you point to using pointerToPointer, i.e. the following holds (I dereference `pointerToPointer, which leads to the value stored behind this pointer, which is a pointer to an int):
max == *pointerToPointer
Is there a way to create an initialize a pointer with one instruction?
yes:
int * a = new int(20); //initialized with 20;
How can I create a pointer on the stack?
int myVar = 20;
int* pVar = &myVar; //copied your code snipped It's alright
Your first example
int* max = new int;
*max = 0;
is indeed creating a new int on the heap, and your variable max saves a pointer to that int. If you're going to use this you're going to have to use delete max; when you no longer need it to avoid memory leaks.
The second example
int myVar = 20;
int* pVar = &myVar;
is creating a int on the stack, pVar now is a pointer to the address where the int is saved in the memory. However if you're using this you don't have to delete the pVar because its not on the heap (you didn't use the new keyword).
The main difference between the two variables (created on heap and stack) is that the stack variable is going to get deleted automatically when it leaves the scopes. The scope is defined by curly braces {}:
int* somefnc()
{
int e1
{
int* e2 = new int(0);
int e3 = 0;
} // int e3 gets automatically deleted here
return e2;
} // e1 gets automatically deleted here
// e2 still exists and has to be manually deleted.
One of the advantage of pointers is when dealing with arrays. If you were to make a char array of x elements on the stack you have to know the number of elements at compile time. If you want to make a char array of x elements at runtime with a dynamic number of elements you'd have to use char* ar = new char[x]; and then access it by ar[x-1] = '\n';.
In order to initialise a variable when creating it on heap you can use var x = new var(args);.
you can pass the value as argument to initialize the memory in heap.
int *iptr = new int(20);
it is initialized with value 20;
stack: contains local variables. so when you create a pointer and assign it with local objects. its pointing to variables in stack. we are not creating pointer on heap
.
Related
Will both the cout statement always print the same value?
#include<bits/stdc++.h>
using namespace std;
int main(){
int* p = new int();
*p = 54;
cout<<p; // it displays the address of int in heap();
delete(p);
p = new int[4];
cout<<p; // it displays the address of first block of memory, of array in heap;
return 0;
}
Will both the cout statement always print the same value?
No. After the delete(p) the memory allocated by the first new expression is deallocated and therefore free to be reused for a later evaluation of a new expression, but there is no guarantee at all that it will be.
That you are reusing the same pointer variable p is irrelevant. It simply stores the address of the storage location returned by the new expressions. You could have used different pointer variables to store the addresses in the same way.
It is also irrelevant that you create a int in the first new expression and a int[4] in the second. Both of the new expressions happen to return a int* which can be stored in the same variable, but nothing would change about the above if you had used simply int in both, or had used completely different types and a pointer variable of type void*.
Will both the cout statement always print the same value?
No. The purpose of delete is to allow memory to be reused so it's possible that the next allocation returns a value just deleted.
But how new manages memory is unspecified.
For example it my be managing pools of different sizes so asking for space 4 integers may not be from the same pool as 1.
It may be that on your platform that simple program will always return the same value twice. But you should regard that as entirely incidental and not something useful.
Whilst in this simple case you may observe the same address assigned to p that is not generally the case. The allocator will allocate a block of memory on a first fit basis, and it is likely in this case that the first available block of the requisite size will be at the same address as the block just released.
If you were to change the example to:
delete(p);
volatile int* dp = new int[4] ;
p = new int[4];
cout<<p;
You will almost certainly observe that the pointer value of p is no longer the same. Moreover if you were to have:
int* p1 = new int[4] ;
int* p = new int[4];
int* p2 = new int[4];
cout << p1;
cout << p2 ;
cout << p ;
delete[] p ;
p = new int[Ox8000];
cout << p;
It is likely that the heap will be fragmented such that the second p allocation will not fit in the space released by the delete.
The delete does not remove the memory from existence, it rather marks the block as available for re-use, returning it to the heap (and coelesing it with adjacent free memory). What you are observing when you get the same pointer value is simple reuse of the space returned to the heap.
I understand that we use this when we need to give a pointer to an array of pointers in the dynamic memory but what I don't understand is that how this works in the stack.
Does this make an array of pointers in the stack too that is pointing to the array of pointers in the heap or does it make a single pointer in the stack that is pointing to the array of pointers in the heap? if yes, then what is the difference between
int **p = new int*[100]
and
int *p = new int[100]
Thanks in advance. I have been trying to understand this for a long time now and have read a lot of documentation online but I still don't understand this.
int **p declares a pointer on the stack which points to pointer(s) on the heap. Each of that pointer(s) point to an integer or array of integers on the heap.
This:
int **p = new int*[100];
means that you declared a pointer on the stack and initialized it so that it points to an array of 100 pointers on heap. For now each of that 100 pointers point nowhere. By "nowhere" I mean that they point neither to a valid chunk of memory, nor they are nullptrs. They are not initialized, thus they contain some garbage value which was in the memory before the pointers were allocated. You should assign something sensible to them in a loop before usage. Note that p[0] - p[99] pointers are not guaranteed to point to adjacent regions of memory if you assign return values of new to them. For example, if you allocate memory for each of them as p[i] = new int[200];, p[0][201] will not reference p[1][2], but will lead to an undefined behavior.
And this:
int *p = new int[100];
is a pointer on the stack which points to an array of 100 integers on the heap.
Don't worry, pointers and arrays in C are always a source of confusion. In general, when you declare an array of, say type int, you create a pointer of type int that points to the first element in a contiguous block of memory that will store ints. For example, if I have a simple array of ints using int *p_to_intarr = new int[3], I get this:
+++++++ <--------- p_to_intarr
| int |
+++++++
| int |
+++++++
| int |
+++++++
In general, if I want an array of type T, I create a pointer to type T like T *ptr_to_Tarr = new T[3].
So what if I want an array of array of ints? Lets just replace the T in with the type of an "array of ints" and this will give us an array of "array of ints". Well we just say in our first example that the type of an array of ints in int *, and so an array of array of ints would be: int* *ptr_to_arrayofintarr = new int*[3]. Note we just replaced the T with int star. This is often written more neatly as int **ptr_to_arrayofintarr = new int*[3].
So int **p could be a pointer to a 2d array. It could also be a reference to a 1d array; depends on the specific case :)
The new expression evaluates to a pointer of some type, pointing to memory that has been allocated in the free store (essentially the heap) but not necessarily in the free store. (It can still be in the free store depending on the context; for instance, consider an initialization-list in a constructor for an object being allocated in the free store.)
The object(s) initialized by new is/are of course in the free store.
In the assignment statements you've shown, you can see the type of the pointer returned by new on the left side of the equals sign, and the type of the free store object(s) to the right of the new. Thus the only object that is locally evaluated (i.e. might be on the stack) is, in the first case, a pointer-to-pointer-to-int, and in the second case, a pointer-to-int. The objects in free space are an array of pointers-to-ints in the first case and a simple array of ints in the second.
Note that just because the array in the first assignment consists of pointers doesn't mean that the pointers themselves actually point to anything yet; new does not magically recursively allocate free space for objects to be targeted by any pointers in an array it creates. (This wouldn't make much sense anyway.)
The ** means that you have a pointer to pointers. In more practical terms, it means you have a two-dimensional array.
Since each element of the array is also a pointer, you need to initialize those pointers as well:
for (int i = 0; i < 100; ++i)
p[i] = new int[200];
This initializes a 100x200 array. You can access the bottom-right corner with p[99][199].
When it's time to delete the pointer you have to reverse the process:
for (int i = 0; i < 100; ++i)
delete [] p[i];
delete [] p;
I found this code online http://www.cplusplus.com/forum/beginner/6644/#msg30551 which is supposed to return an array from a c++ function. I would like an explanation illustrating how this function operates with respect to memory allocation, stacks, heaps, pointers etc.
int *f(size_t s){
int *ret=new int[s];
for (size_t a=0;a<s;a++)
ret[a]=a;
return ret;
}
I.
int *ret=new int[s];
1. allocate memory for ret on the stack - this is an int pointer
2. allocate continuous memory with size s * sizeof(int) on the heap
3. make ret to point to the first element of the allocated memory (from 2.)
II.
for (size_t a=0;a<s;a++)
ret[a]=a;
allocates memory on the stack for a
loop through the allocated memory in I., assigning values to each element
After the end of the for-statement, a is no longer accessible (it's available only in the for)
III.
return ret;
return a copy of the ret pointer, which points to the first element of the created in I. array, initialized in II.
After the return, ret is "destroyed".
The caller of this function must not forget to deallocate (free) this memory, invoking delete[].
For example:
int * my_array = f( 6 );
// do sth with my_array
delete[] my_array;
Actually, the function doesn't return an array of ints (i.e. int[N]). What it returns is a pointer to an int (int *). It turns out that this pointer points to the first element of an array of s elements of type int.
Notice that the memory is allocated with new:
int *ret = new int[s];
Therefore, the array of ints pointed by ret has dynamic storage duration. Among other things, this implies that
1) the compiler will not automatically call each array element's destructor. (In this case this isn't a problem because the elements are of type int but could be if, instead, the elemets where of a class type with a non-trivial destructor.)
2) the compiler will not automatically free the allocated memory.
To contrast, consider the following code:
void g() {
int p[10]; // allocates 10 integer in the stack
// use p ...
}
When g terminates the compiler will perform the aforementioned operations. For this to work, the size of the array (10 in this example) must be set at compile time. If you don't know the size at compile time than you need new as in the original code.
For dynamic allocated arrays, it's the programmer's responsibility to ensure that the two aforementioned operations are performed when the array is no longer needed. To accomplish this, you must call delete[]:
delete[] p; // where p is a `int*` with the same value as `ret`
In practice, this is more difficult than it seems due to the possibility of
exceptions being thrown. For instance, consider this code
void foo() {
int* p = f(10); // where f is in the question
// ... use the array pointed by p
a_function_that_might_throw();
delete[] p;
}
If a_function_that_might_throw does throw an exception then the execution
never reachs the point where p is deleted. In this case, the memory
allocated by new (inside f) will not be freed (it leaks) until the
program terminates.
To avoid this problem, instead of a raw pointer (e.g. int*) it's better to
use a smart pointer (e.g. std::unique_ptr or std::shared_ptr).
Finally, by default, the memory allocated by new is heap memory. However,
you can change this behavior.
int *ret=new int[s];
This line defines a int* called ret with automatic storage duration. It initialises ret with the pointer returned by the new-expression new int[s]. This new-expression creates an array of s ints with dynamic storage duration, returning a pointer to the first element in that array.
So we now have two objects: an int* with automatic storage duration and an int[] with dynamic storage duration.
for (size_t a=0;a<s;a++)
This is a for statement. The for-init-statement defines a size_t object called a and initialises it to 0. The condition checks whether a is less than s. The final expression increments a. This means that a loops in the range [0, s).
ret[a]=a;
This assigns the value of a to the ath element in ret. That is ret[0] will have the value 0, ret[1] will have the value 1, and so on.
The a object is now destroyed because it had automatic storage duration and we have reached the end of its scope (the for statement).
return ret;
This returns the value of ret, which as you remember was an int*. The return value of the function is therefore an int* pointing at the first element of the dynamically allocated array.
The ret object is now destroyed because it had automatic storage duration and we have reached the end of its scope (the f function). Note that this is just the pointer inside the function. The dynamically allocated array still exists and the returned pointer still points to it.
You must, at some later point, remember to delete[] the returned pointer.
int *ret = new int[s];
This dynamically (~ on the heap) allocates an array of s integers and stores a pointer to it (actually, to its first element) in ret.
I believe the rest of the function is straightforward.
So the function is handing back a pointer to a dynamically allocated array. It's not really safe; if the caller does not store the return value and later call delete[] on it, it will leak.
What is the difference between declaring a new integer array by using int someInts[3], versus using int* someInts = new int[3]?
There are 2 main differences:
The first will allocate a memory on the stack, that will be unavailable once the function returns.
The second will allocate a memory on the freestore, which will be available until deleted.
The first someInts is an array of ints, you cannot assign new address to it.
The second is a pointer to int, so you may assign a new address to it.
The difference that's generally important (especially when you're dealing with something other than ints) is that with when you use the latter (int *someints = new int[3];) you have to explicitly delete the data when you're done using it.
Most of the time, you want to use std::vector<int> someints(3); instead. This will (normally) allocate the space for the data similarly, but it'll automatically delete that space when the variable goes out of scope (including, for example, leaving the scope via an exception being thrown, which is much more difficult to handle correctly when you allocate/free the memory manually).
Declaring int* someInts = new int[3] allocates the memory on the heap. Declaring int someInts[3] allocates it on the stack.
When you do someInts[3], you allocate memory on the stack, this means that it will delete itself (good) but if you want to access after the function has ended you'll run into trouble as it will already have been deleted. IE:
int* returnPointerThingy(){
int someInts[3];
someInts[0] = 3;
someInts[1] = 2;
someInts[2] = 1;
return someInts
}
This will return a null pointer since someInts has been deleted. If you try to access something in someInts god help you.
If this is similar to what you which to do you want to use the new keyword. It will allow you to allocate something on the "Heap" and it will live after the function it was declared in has ended. Thus this:
int* returnPointerThingy(){
int* someInts = new int[3];
someInts[0] = 3;
someInts[1] = 2;
someInts[2] = 1;
return someInts
}
Will not return a null pointer and you will be able to use the values stored by someInts. However this comes with a drawback, you must delete someInts like this:
delete [] someInts
So you don't end up with memory leaks, when the heap gets taken up by pointers and such.
It depends on your situation for which to use as both are better in their own situations.
In many tutorials, the first code samples about dynamic memory start along the lines of:
int * pointer;
pointer = new int; // version 1
//OR
pointer = new int [20]; // version 2
They always proceed to explain how the second version works, but totally avoid talking about the first version.
What I want to know is, what does pointer = new int create? What can I do with it? What does it mean? Every tutorial without fail will avoid talking about the first version entirely. All I've found out (through messing about) is this:
#include <iostream>
using namespace std;
int main()
{
int * pointer;
pointer = new int;
pointer[2] = 1932; // pointer [2] exists? and i can assign to it?!
cout << pointer[2] << endl; // ... and access it successfully?!
};
The fact that I can subscript pointer tells me so far that pointer = new int implicitly creates an array. But if so, then what size is it?
If someone could help clear this all up for me, I'd be grateful...
My teacher explained it like this.
Think of cinema. The actual seats are memory allocations and the ticket you get are the pointers.
int * pointer = new int;
This would be a cinema with one seat, and pointer would be the ticket to that seat
pointer = new int [20]
This would be a cinema with 20 seats and pointer would be the ticket to the first seat. pointer[1] would be the ticket to the second seat and pointer[19] would be the ticket to the last seat.
When you do int* pointer = new int; and then access pointer[2] you're letting someone sit in the aisle, meaning undefined behaviour
This is a typical error in C and C++ for beginners. The first sentence, creates a space for holding just an int. The second one creates a space for holding 20 of those ints. In both cases, however, it assigns the address of the beginning of the dynamically-reserved area to the pointer variable.
To add to the confusion, you can access pointers with indices (as you put pointer[2]) even when the memory they're pointing is not valid. In the case of:
int* pointer = new int;
you can access pointer[2], but you'd have an undefined behavior. Note that you have to check that these accesses don't actually occur, and the compiler can do usually little in preventing this type of errors.
This creates only one integer.
pointer = new int; // version 1
This creates 20 integers.
pointer = new int [20] // version 2
The below is invalid, since pointer[2] translates as *(pointer + 2) ; which is not been created/allocated.
int main()
{
int * pointer;
pointer = new int;
pointer[2] = 1932; // pointer [2] exists? and i can assign to it?!
cout << pointer[2] << endl; // ... and access it succesfuly?!
};
Cheers!
new int[20] allocates memory for an integer array of size 20, and returns a pointer to it.
new int simply allocates memory for one integer, and returns a pointer to it. Implicitly, that is the same as new int[1].
You can dereference (i.e. use *p) on both pointers, but you should only use p[i] on the pointer returned by the new int[20].
p[0] will still work on both, but you might mess up and put a wrong index by accident.
Update: Another difference is that you must use delete[] for the array, and delete for the integer.
pointer = new int allocates enough memory on the heap to store one int.
pointer = new int [20] allocates memory to store 20 ints.
Both calls return a pointer to the newly allocated memory.
Note: Do not rely on the allocated memory being initialized, it may contain random values.
pointer = new int; allocates an integer and stores it's address in pointer. pointer[2] is a synonym for pointer + 2. To understand it, read about pointer arithmetic. This line is actually undefined behavior, because you are accessing memory that you did not previously allocate, and it works because you got lucky.
int* p = new int allocates memory for one integer. It does not implictly create an array. The way you are accessing the pointer using p[2] will cause the undefined behavior as you are writing to an invalid memory location. You can create an array only if you use new[] syntax. In such a case you need to release the memory using delete[]. If you have allocated memory using new then it means you are creating a single object and you need to release the memory using delete.
*"The fact that i can subscript pointer tells me so far that I pointer = new int implicitly creates an array. but if so, then what size is it?"
*
This was the part of the question which I liked the most and which you emphasize upon.
As we all know dynamic memory allocation makes use of the space on the Stack which is specific to the given program.
When we take a closer look onto the definition of new operator :-
void* operator new[] (std::size_t size) throw (std::bad_alloc);
This actually represents an array of objects of that particular size and if this is successful, then it automatically Constructs each of the Objects in the array. Thus we are free to use the objects within the bound of the size because it has already been initialized/constructed.
int * pointer = new int;
On the other hand for the above example there's every possibility of an undefined behaviour when any of
*(pointer + k) or *(k + pointer)
are used. Though the particular memory location can be accessed with the use of pointers, there's no guarantee because the particular Object for the same was not created nor constructed.This can be thought of as a space which was not allocated on the Stack for the particular program.
Hope this helps.
It does not create array. It creates a single integer and returns the pointer to that integer. When you write pointer[2] you refer to a memory which you have not allocated. You need to be carefull and not to do this. That memory can be edited from the external program which you, I belive, don't want.
int * pointer; pointer = new int; // version 1
//OR
pointer = new int [20] // version 2
what I want to know is, what does pointer = new int create? what can I do with it? what does it mean? Every tutorial without fail will avoid talking about the first version entirely
The reason the tutorial doesn't rell you what to do with it is that it really is totally useless! It allocates a single int and gives you a pointer to that.
The problem is that if you want an int, why don't you just declare one?
int i;