I'm trying to get this clear up in my mind.
int* arrayA = new int[3];
int arrayB[3] = {1,2,3}
arrayA = arrayB;
Does the value of arrayB get copied over to arrayA?
Or does arrayA become a pointer to arrayB?
Naked new is evil, especially for arrays. Use std::vector if you need dynamic array and std::array if you need static one.1
Now the actual answer is simple. arrayA is a pointer. So it's made to point to arrayB. That has additional effect that:
you now leaked the allocated pointer.
attempt to delete arrayA will now crash or something else unpleasant, because you would be trying to free unallocated memory.
Actually while C++ allows assigning structures and classes, it does not support assigning arrays at all. Unless part of an object either managed as in std::vector or as array member as in std::array (note: std::array is C++11).
1 The main reason is that the containers guarantee the resources will be released in their destructors, so called RAII idiom, avoiding most opportunities for memory leaks and dangling references.
int* arrayA = new int[3];
arrayA now stores the address in memory of a different memory block thats large enough to contain 3 ints which is stored on the heap.
int arrayB[3] = {1,2,3};
arrayB is a block of memory thats large enough to contain 3 ints which is stored on the stack.
arrayA = arrayB;
Copies the address of the memory block that's stored on the stack into the variable arrayA. You have now lost the only reference to memory block stored on the heap, and have no way to free up the memory (a memory leak)
The memory stored on the stack and now pointed to by arrayA will not be safe to access when the current function returns. In particular returning arrayA (or arrayB) is not safe.
For
Does the value of arrayB get copied over to arrayA?
Nope. It will not copy arrayB to arrayA. If you want to do so, you can do like,
for (int i=0;i<3;i++) arrayA[i]=arrayB[i]; //This is two arrays has same value
does arrayA become a pointer to arrayB?
Yes. It become a pointer to array of arrayB. After arrayA = arrayB; statement, memory allocated in the first line can not be accessible and it is a leak.
arrayA=arrayB; result in copying the address of arrayB to arrayA. arrayA will start pointing to the arrayB. Check it using,
printf("\n Base address of A[%u] base address of B[%u]", arrayA, arrayB);
Hope this helps.
Array name represents the base address of the array.
arrayA=arrayB;
stores the base address of arrayB to arrayA. The further values can be accessed by incrementing the pointer arrayA.
i.e
*(arrayA) value is 1
*(arrayA+1) value is 2
*(arrayA+2) value is 3
The memory created should be freed at the last using
delete[] arrayA
Q. Does the value of arrayB get copied over to arrayA?
Ans. NO
Or
Q. does arrayA become a pointer to arrayB?
Ans YES.
But the memory chunk which you allocated using new is lost. As no one is having the address which was starting point of that chunk.
This is vindicated by this program :
#include<iostream>
using namespace std;
const int MAX=4;
int main(){
int* arrayA = new int[MAX];
for(int i=0;i<MAX;i++){ arrayA[i]=i; }
int arrayB[MAX] = {10,20,30,40};
arrayA = arrayB;
for(int i=0; i<MAX;i++){ cout<<" a["<<i<<"] = "<<arrayA[i]<<endl; }
return 0;
}
The output of this code is :
a[0] = 10
a[1] = 20
a[2] = 30
a[3] = 40
on
g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
which is true in general as well.
visualization of this is somewhat like this
arrayA-> [0][1][2][3]
arrayB-> [10][20][30][40]
Intially arrayA has address of [0] ( + sum extra memory on the negative indexes for size used by compiler to do the de-alloctation ).
after
arrayA=arrayB;
arrayA has address of [10];
suppose you call delete on arrayA what shall happen ??
*** Error in `./a.out': double free or corruption (out): 0x00007fff561281d0 ***
This is evident from the following code also
#include<iostream>
using namespace std;
const int MAX=4;
int main(){
int* arrayA = new int[MAX*2];
for(int i=0;i<MAX;i++){ arrayA[i]=i; }
int* arrayC = new int[MAX];
int j=0;
for(int i=MAX*100;i>=0;i-=10,j++){ arrayC[j]=i; }
arrayA = arrayC;
for(int i=0; i<MAX;i++){ cout<<" a["<<i<<"] = "<<arrayA[i]<<endl; }
delete[] arrayA;
return 0;
}
The out put is :
a[0] = 400
a[1] = 390
a[2] = 380
a[3] = 370
*** Error in `./a.out': free(): invalid next size (fast): 0x0000000002028040 ***
Aborted (core dumped)
Just pay attention to :
"invalid next size"
This clearly says about the size value written before the arrayA in the negative indexes.
Related
int *arr = new int(10);
int *arr = new int[10];
It is the code of dynamic memory allocation in c++.
But I am not getting What is the difference between these two.
For a simple example, let's talk about what happens on the stack.
int x(10)
This generally means assigning an value to an int named x.
int x[10]
This generally means creating an array named x of 10 elements.
So, when it come to dynamic memory, it's the same thing.
int* x=new int(10)
This creates a single integer on the heap and assigns it the value 10.
int* x=new int[10]
This creates an array of 10 integers on the heap.
int *arr = new int(10); allocates heap memory for a single integer, initialized to 10.
int *arr = new int[10]; allocates heap memory for an array of 10 integers, none of which are initialized to any specific value.
Keep it in mind: The ( ) and { } mainly used for initialization in declarations. And [ ] is mainly an indexing operator. So in the first statement, you are trying to allocate an int memory with 10 as the initial value. And in the second statement, you are trying to allocate a 10 int block array with no default initialization.
I am kind of confused with the pointers.
Say if I have this:
int size;
int bytes;
int numbers;
int *ptr;
ptr = new int[500];
My question is the pointer at first points to any specific variable or just to overall int variables. What if I want a pointer to point only at numbers variable.
I have a tail question if you don't mind. I am trying to allocate dynamic memory to my array, is this valid? :
int numbers[20];
int *ptr;
ptr = new int[size];
Would this give a heap memory to my array?
I am working with an array of very large size and there is no other way to work with it without using heap memory.
P.S: I can't use vector at this point.
int *ptr is an pointer to an int variable. It doesn't matter what variable, as long as it is an int so you could have the following.
int size;
int bytes;
int numbers;
int *ptr;
ptr = &size;
ptr = &bytes;
ptr = &numbers;
I use the & symbol because this gives the actual address of the variable not its value. Pointers can only store the address of a variable.
If you then wanted to use the actual values that the pointer points to, you need to deference it, like so
int number = 5;
int *ptr;
ptr = &number;
cout << *ptr;
//5
As for your second question. Yes that would give you a valid pointer to an array on the heap.
For more information I suggest looking up what an array actually is, since you might be confused why you don't need to use the & symbol when assigning a pointer to an array.
int *ptr is uninitialized, so it actually points to "garbage values" or in this case, random memory addresses. Check out Uninitialized pointers in code
If you want int *ptr to point to the value of numbers, you should first initialize int numbers, because this can cause Undefined behavior if you try to dereference it.
You can assign the ptr equal to numbers by using the Address-of operator &. Then use the dereference operator * to grab the value of ptr.
numbers = 4;
ptr = &numbers;
cout << *ptr << endl;
This will print 4.
int arNumbers[20];
gives you memory from stack and is not dynamic and compiler would take care of releasing the memory.
int *pNumbers = new int[20];
gives you memory from heap and is dynamic and you need to delete it when you are done:
delete[] pNumbers;
if you need 20 numbers, one of them is enough.
here if I use delete or delete[] the output is still 70. Can I know why?
#include<iostream>
using namespace std;
int main()
{
int* c = new int[100];
for(int i=0; i<98; i++)
{
c[i] = i;
}
cout<<c[70]<<endl;
delete[] c;
or
delete c;
cout<<c[70]<<endl; //outputs 70 even after delete[] or delete
return 0;
}
Accessing deleted memory is undefined behavior. Deleting with the wrong delete is also UB. Any further discussion is pointless in the sense that you cannot reliably expect any outcome.
In many cases, UB will just do the "correct" thing, but you need to be aware that this is completely "by chance" and could change with another compiler, another version of the same compiler, the weather... To get correct code, you need to avoid all cases of UB, even those that seemingly work.
Using new will just allocate some memory to your program and return a pointer pointing at the said memory address, reserving as much memory as needed for the datatype. When you use delete later, it "frees" the memory, but doesn't delete it's content. If you had an int with the value 70 stored at that address, it will still contain 70, until another application wants some memory, gets said address and puts another value in there.
If you use new to allocate memory for an array, you will reserve following blocks of memory until there are enough blocks for your specified array length.
Let's say you do the following:
int main() {
int* array = new int[10]; // array now points to the first block of the allocated memory
delete array; // since array points to the first block of the array, it will only free that block, but nothing else, causing a memory leak
delete[] array; // will free all memory allocated by the previous new
// Note that you should never free allocated memory twice, like in this code sample. Using delete on already freed memory is undefined behaviour!
]
Always use delete for single variables and delete[] for arrays.
A demonstration of your problem:
int main() {
int* c = new int[10]; // We allocate memory for an array of 10 ints
c[0] = 1; // We set the value of the first int inside the array to 1
delete[] c;
/*
* We free the previously allocated memory.
* Note that this does not delete the CONTENT of the memory!
* c does still point towards the first block of the array!
*/
std::cout << c[0];
/*
* Firstly, this is undefined behaviour (Accessing deallocated memory).
* However, this will output 1,
* unless some other process allocated the memory at the address
* and filled it with another value already. (Very unlikely)
*/
return 0;
}
If you want to delete / overwrite the content of the deleted memory, you can use std::memset.
Example:
#include <cstring>
int main() {
std::size_t length = 10;
int* c = new int[length];
c[0] = 1;
std::cout << c[0] << std::endl; // Will output 1
std::memset( c, 0, length ); // Fill the memory with 0 bytes
delete[] c; // Now we free the array's memory
std::cout << c[0] << std::endl; // Will output 0
}
As others pointed its undefined behaviour and anything can happen.
These can be easily caught with the help of tools like valgrind.
First off, I apologize if this has been asked before. I can't seem to find the right info.
The following code does not print "300" as I thought it would:
#include <iostream>
int main()
{
int *array;
int *arrayCopy = array;
array = new int[4];
array[0] = 100;
array[1] = 200;
array[2] = 300;
array[3] = 400;
std::cout << arrayCopy[2];
return 0;
}
However, it does, if I move the line
int *arrayCopy = array;
below the line that follows it in the above code. Why is that?
(PS: I know there is a memory leak, and that std::vector is better... I'm just curious).
No, when you do int *arrayCopy = array; you capture the value of array into arrayCopy at that moment of time, so if you modify (note that initially array is pointing to some random location, you make it point to a correct location by doing new) the array after you copied to the arrayCopy then those changed will not be reflected back to arrayCopy.
Maybe you're thinking of using a reference to a pointer? Here's what happens with your current code:
int *array; // Currently points to an undefined (invalid) memory location.
int *arrayCopy = array; // Now this points to the same undefined memory location as array.
array = new int[4]; // Now array points to valid memory, but arrayCopy still points to undefined space.
If you did something like this though, it's different:
int *array; // Points to undefined
int *&arrayCopy = array; // This is a reference to array. That means if you change array, arrayCopy will also reflect the changes.
array = new int[4]; // Now since array points to valid space, arrayCopy does too.
Technically, this isn't entirely true because different things are happening. A reference is essentially the same level of indirection as a pointer, except the compiler does all the dereferencing for you. But what I described is essentially how it works. If you just stick the extra & in there, your code will do what you were thinking.
int *array; // array is ???
int *arrayCopy = array; // copy is ???
array = new int[4]; // array is valid pointer, copy still ???
This code snippet does the following:
creates an int pointer of indeterminate value (could be anything).
copies that indeterminate value to the copy.
changes the value of the original pointer to point to a newly created array.
In other words, the third line "disconnects" the two pointers, leaving the copy still pointing to an indeterminate location.
Dereferencing that pointer copy is undefined behaviour, not something you want to muck about with.
In contrast, if the sequence is changed to (as mentioned in your question):
int *array; // array is ???
array = new int[4]; // array is valid pointer
int *arrayCopy = array; // copy is now also the valid pointer
then the copy pointer is set to the original after the original has been initialised to point to the array. No disconnect occurs, so that array[2] is effectively the same as arrayCopy[2].
Is it possible to copy a dynamically allocated array pointer prior to memory allocation?
No.
However, you can do this:
int *array;
int *&arrayReference = array;
int *array; // points to some random value
int *arrayCopy = array; // points to the same value
array = new int[4]; // array points to a new value, arrayCopy does not
If you want to make a pointer that points to whatever "array" points to at all time, create a double pointer
http://computer.howstuffworks.com/c32.htm
I want to know what is happening in memory when you declare:
int **array;
If I am not mistaken...
You have a multidimensional array arr[i][j] and
**arr addresses to arr[0][0]
*((*arr)+1) addresses to arr[0][1]
*(*(arr+1)+1) addresses to arr[1][1]
Sample code in C++
#include <iostream>
using namespace std;
int main()
{
int **arr;
arr = new int*[5];
for(int i = 0; i < 5; i++)
arr[i] = new int[5];
arr[0][1] = 1;
cout << *((*arr)+1); // prints 1
cout << arr[0][1] = 1; // prints 1
}
It creates a variable to store a pointer to an int pointer.
The compiler reserves four bytes (on a 32bit system, eight bytes on 64bit) to store a pointer (that would point to another pointer, that would point to an int). No further memory allocation is done, it is left to the programmer to actually set the pointer to point to some other memory location where the int*/array/... is stored.
You're declaring a pointer variable, so you're allocating enough space for one memory address (depends on your platform/compiler/etc.)
The type system will ensure that the only addresses you assign into it contain other memory addresses, and that these addresses represent the actual address of an integer variable.
To use your pointer-to-pointer, you dereference it once (to get the address that actually points to the integer), and then a second time (to get the actual integer).
You can bypass the type system by explicitly casting to something else (e.g., i=&pDouble) but that is not recommended unless you're sure you know what you're doing.
If you have a two-dimensional array, you can think of it conceptually as one single-dimensional array of single-dimensional arrays representing rows. The first level of indirection would be to pick the row, and the other one to pick the cell in the row.
It's a pointer to an int pointer. This is often used to declare a 2D array, in which case each int pointer is an array and the double pointer is an array of arrays.