what is the difference between () and [] dynamic allocation? - c++

Can anyone explain the difference between the following two forms and what does each do:
int *p = new int[5];
and
int *p = new int(5);
Query
1) What are we allocating in both the cases i.e either integer or array ??
2) What will be the initial value after allocation in both cases??
3) And reference from where i can found about this

The syntax of a new-expression is as follows:
the keyword new
optional arguments, enclosed in parentheses
type
optional initializer
In new int[5], the type is int[5] and there is no initializer. Thus, an array of 5 ints is allocated, they are not initialized, and a pointer to the first element is returned.
In new int(5), the type is int and the initializer is (5), so one int is allocated, it is initialized with the value 5 (just like in int x(5);), and a pointer to it is returned.

int *p = new int[5];
allocates an "array" of integers with length 5. It returns a pointer to the beginning of 5 contiguous memory blocks, each of which can hold an int.
int *p = new int(5);
allocates a pointer to a single integer initialized to the value 5.

In the first instance it allocates a integer array of size 5. In this case, the elements in the array are uninitialized.
In the second instance it allocates one integer with value 5.
References:
http://www.cplusplus.com/reference/new/operator%20new/
http://www.cplusplus.com/reference/new/operator%20new[]/

here I will answer all questions one by one
Question 1:What are we allocating in both the cases i.e either integer or array ??
int *p = new int[5]; // you are allocating an array
int *p = new int(5); // you are allocating an integer
Question 2:What will be the initial value after allocation in both cases?
int *p = new int[5]; // Initially there will be random value on all indexes
int *p = new int(5); // Initially value will be 5
Question 3:And reference from where i can found about this?
Check the following links
http://www.cplusplus.com/doc/tutorial/dynamic/
http://en.wikipedia.org/wiki/Initialization_%28programming%29

Square brackets are used to denoting arrays of its elements.
So in this statement
int *p = new int[5];
There is allocated an array of 5 integer elements that are not initialized. Compare with definition
int a[5];
In this statement
int *p = new int(5);
there is allocated an object of type int that is initialized by 5. Compare it with the following definition
int x = int( 5 );
or simply
int x = 5;

Related

C++ array declaration on heap?

In C++ we can write:
int arr[] = {20,3,2,0,-10,-7,7,0,1,22};
//Smal Note: Why int *arr = {20,3,2,0,-10,-7,7,0,1,22}; won't work? I learnt I can replace [] with *
but what if I want to allocated arr on heap in one line?
I tried:
int arr[] = new int {20,3,2,0,-10,-7,7,0,1,22};
In function arguments, int[] means "an array of unknown size", and is technically equivalent to int*. (when the pointer is interpreted as a pointer to the first integer in an array).
But in your declaration, int[] means "an array whose size is determined by the initializer", and that is a very well-known size.
new int[] does create an array on the heap, but it returns a pointer to the first element. You might notice a similarity here with function arguments - it's easy to convert from an array to a pointer.
std::vector<int> creates an array on the heap too, but the vector object which manages the array can live anywhere. That's often a lot more convenient.
If you write int arr[] = {20,3,2,0,-10,-7,7,0,1,22}; your arr is usually stored on the stack, just like int a=20, b=3, ...;. In this case, the right-hand side is an initializer, which just tells how int arr[] is initialized.
On the other hand, if you write int *arr = new int[]{20,3,2,0,-10,-7,7,0,1,22}; the array is created on the heap, which can only be accessed via pointers, and the pointer pointing to the array is assigned into int *arr which in turn is on the stack.
So in the context of declaration, int[] and int* are completely different things. But both int[] array and int* array can be accessed using the [] operator, e.g. arr[2] which is synonymous with *(arr+2). And when you use int[] or int* as an argument of a function, they are completely interchangeable.

Why is the size of a heap-allocated array required with initializer-list initialization?

While I can write
int n[] {1, 2, 3};
I cannot write
int *m = new int[] {1, 2, 3};
which should be
int *m = new int[3] {1, 2, 3};
What is the reason for this?
Remember that new actually is an operator in C++.
This is because how new operator is defined; i.e. it needs the size of the requested memory as an input parameter explicitly. So, it would not be deduced by the count of initializer list members.
To Understand this you need to understand how new operator works.new returns a pointer to the beginning of the new block of memory allocated. so when we say
int* p = new int;
we are allocating memory to contain one single element. But when we say
int* foo = new [3];
we are allocating a block of memory for elements of type int, where "3" is the number of memory block for the integer type. So this tells the compiler that allocate memory for 3 integers.
When we do this
int* p = new int[3]{1,2,3}
we are asking the compiler to allocate 3 memory location that will store value of type integer. At the same time we are also assigning values to those memory locations.
Now if we do this
int* p = new int[] {1,2,3}
we are not telling the compiler how much memory to allocate, but at the same time we are trying to assign to 3 memory location but we have not allocated that much memory. In this case the compiler only allocates 1 block of memory. So the first value gets assigned. This will cause a run time error.
Now what is strange is that , if the below is allowed and the compiler is intelligent enough to assign 3 values
int n[] = {1, 2, 3}
why not in this case
int *p = new int [] {1,2,3}
I believe that is the problem because of how the new operator is designed. You can probably try to overload the new operator and get around this problem.
Hope this helps.
EDIT: I tried some dummy code in VS. It seems if you do this
int* p = new int [] {1,2,3}
its a crash. But when you do this
int* p = new int []{1}
this perfectly fine. This proves that compiler is interpreting it as a command to allocate 1 block of memory only.

C++ assigning arrays to eachother; type int* = type int works but not int = int*?

I have a question:
Why does this throw an error (cannot convert from int* to int[5])
int static_Array[5];
int *dynamic_Array;
dynamic_Array = new int[5];
static_Array = dynamic_Array;
while this works fine?
int static_Array[5];
int *dynamic_Array;
dynamic_Array = new int[5];
dynamic_Array = static_Array; //This line changed
I am guessing that types int can be converted to int* by the compiler?
But then why couldn't int be converted to int* by the compiler as well?
Anyone can provide an actual explanation?
Thanks!
When a raw array is specified in a context where a pointer is expected, it converts to pointer to first item (in the sense of producing that pointer value), which is called a type decay.
Contexts where that doesn't happen include sizeof expression, typeid expression and binding to reference to array.
But essentially that means that raw arrays are not assignable, and of course you cannot assign a pointer to an array variable, for what should the result be.
However, if you put an array in a struct, then you can assign the struct. And that's what std::array is. But when you want an assignable dynamic size array, use std::vector.
In passing, there is is also a similar type decay for functions.
This one:
int static_Array[5];
int *dynamic_Array = new int[5]; // 1.
dynamic_Array = static_Array; // 2.
dynamically allocates an array and stores the address of first element in pointer dynamic_Array
overwrites this address with an address of the first element of the static_Array
But this one:
int static_Array[5];
int *dynamic_Array = new int[5];
static_Array = dynamic_Array;
attempts to initialize an array using an address (thus compiler gives error about invalid pointer to array conversion).
So why the first one works?
Because static array (on the right side) immediately decays to a pointer. This can not work the other way, there is no guarantee that this pointer points to an array.
int static_Array[5];
Here static_Array is const pointer to static_Array[0], you cannot modify it like,
static_Array = dynamic_Array;

Pointers and assignment

Why is
int *a = new int[10];
written as
int *a;
a = new int[10];
instead of
int *a;
*a = new int[10];
?
The way I see it, in the second block of code you're saying a, which was a pointer variable, is now an array. In the third block of code you're saying the thing a points to is now an array. Why does the second make more sense than the third?
new int[10] returns a pointer to the first element in the array (which is of type int*). It does not return a pointer to the array (which would be of type int(*)[10]).
a = new int[10] means make a point to the first element of the dynamically allocated array. *a is not a pointer at all. It is the object pointed to by the pointer a (which is of type int).
Note that if you actually had a named array object, the syntax would still be the same:
int x[10];
int* a = x;
Why? In C++, in most cases, whenever you use an array, it is implicitly converted to a pointer to its initial element. So here, int* a = x is the same as int* a = &x[0];.
(There are several cases where the array-to-pointer decay does not occur, most notably when the array is the operand of the & or sizeof operators; they allow you to get the address of the array and the size of the array, respectively.)
*a = ... means assign value to memory that I'm pointing to
a = ... means assign me new memory address that I should point to
The type int* is a pointer to an int. If you apply the derefence operator to such a pointer, you get an int (or, more precisely, actually a reference to an int, i.e. a int&) That is, when you write
int* a;
*a = new int[10]; // ERROR: incompatible types `int&` and `int*`
you try to assign the result of new int[10] which is of type int* to an object of type int&. This isn't supposed to work.
In the third block of code you're saying the thing a points to is now an array.
You're not, though.
new doesn't evaluate to an array, but to a pointer to a block of memory. That's why you're assigning to a pointer.
It's a consequence of dynamically-allocated objects not being directly reachable in the current lexical scope.
Because this :
a = new int[10];
and this :
*a = new int[10];
are completely different things. The 2nd is the pointer dereferencing.
This:
int *a = new int[10];
and this
int *a;
a = new int[10];
are same things.
You are assigning to a pointer variable, so you have to write a.
Would you have written
int* a = new int[10];
this would be more obvious that the type of a is int* (pointer to an `int).
Because operator new returns the address of the object(s) it creates. *a is not an address, it's the int that a points at.
When you declare a pointer,
int *a;
in the memory:
Memory Address Variable Identifier Variable Value
-------------- -------------- --------------
0xAE934904 a ?
When you create a dynamic array, you have 10 integer numbers:
a = new int[10];
Memory Address Variable Identifier Variable Value
-------------- -------------- --------------
0xH3948300 - ?
0xH3948304 - ?
0xH3948308 - ?
0xH394830C - ?
...
(in total, 10 integers) and value of a becomes 0xH3948300.
Memory Address Variable Identifier Variable Value
-------------- -------------- --------------
0xAE934904 a 0xH3948300
On the other hand, if you write *a = new int[10]; this is *(?) which means go to the value that is stored at memory location ?. *(?) is probably not a memory space where you can store memory address. If you want to assign a value to the pointer, you simply type the identifier name, a.

int (*p) [4]?

int (*p) [4] ;
Is "p" pointer to array of 4 integers ?? or what ??
and How can I call "new" for this pointer ??
Is "p" pointer to array of 4 integers?
Correct!
How can I call "new" for this pointer?
For example, p = new int[7][4].
int (*p)[4] is, indeed, a pointer to an array of four ints.
You can dynamically allocat an object of type "pointer to array of four int" as follows.
int (**ptr)[4] = new (int (*)[4]);
Note, no space for any ints is allocated; only the pointer itself.
You can allocated an array of 4 ints as follows:
int *ptr = new int[4];
What you can't do (without explicit casting) is assign a pointer to a dynamically allocated array of 4 int to a pointer of type int (*)[4]. Whenever you allocate an array via new, even if you use a typedef, the type of the new expression is a pointer to the first element of the array; the size of the array is not retained in the type of the new expression.
This is because new[] expressions can allocate arrays where the size of the array is chosen at runtime so would not always be possible (or even desirable) to encode the array size into the type of the new expression.
As has been suggested, you can dynamically allocate an array of one array of 4 int. The size of the first array is lost from the type information and what you get is a pointer to the first element of the array (of size 1) of the arrays of four int.
int (*p)[4] = new int[1][4];
Even though it is an array of just 1 (arrays of 4 int), you still need to use delete[] to deallocate p.
delete[] p;
The online CDECL evaluator is a helpful resource for questions like this:
cdecl
C gibberish ↔ English
int (*p)[4];
declare p as pointer to array 4 of int