LogicBreaker
LogicBreaker

Reputation: 105

Dynamic array allocation

I'm wondering why new doesn't seem to retain the array information and just returns an int*:

#include <iostream>
using namespace std;

typedef int (*p_to_array)[80];
typedef int arr[80];




int main() 
{
   arr a;
   p_to_array p = &a;  //fine

   p_to_array p2 = new arr; // incompatible types 

   return 0;
}

Upvotes: 7

Views: 642

Answers (3)

Columbo
Columbo

Reputation: 60979

You can either use the array syntax or a typedef-name to allocate arrays with new - both is allowed and equivalent according to [expr.new]/5:

When the allocated object is an array (that is, the noptr-new-declarator syntax is used or the new-type-id or type-id denotes an array type), the new-expression yields a pointer to the initial element (if any) of the array.

As you can see, for arrays, solely a pointer to the initial element is given; Not a pointer to the array object itself. Thus the type yielded is int*, not int (*)[N].

The reason why a pointer to the initial element is returned is quite simple: It is the pointer that you want to work with.
We want to write

auto p = new int[50];
// Or
int* p = new int[50];

So as to be able to use normal subscripting:

p[49] = 0xDEADBEEF;

That would be nonsensical with p if it was of type int(*)[50] pointing to the array object, because the subscript would add 49*50*4 to the address, not just 49*4 - because of subscript semantics and pointer arithmetics.
We would have to either use two subscripts:

p[0][49] = ...;

Which is horrific and unnecessarily redundant. Or we could use a cast:

int* p = static_cast<int*>(new int[50]); // Or with auto

But that is ugly too.
To avoid such hassles, this rule was introduced.

Upvotes: 4

Bartek Banachewicz
Bartek Banachewicz

Reputation: 39370

I might be totally wrong about this: (i.e. this is little more than an educated guess)

new arr;

is equivalent to:

new int[80];

which by language rules returns int*.


From cppreference.com: (thanks to @interjay for pointing out I actually cited the irrelevant part)

The new-expression returns a prvalue pointer to the constructed object or, if an array of objects was constructed, a pointer to the initial element of the array.

My understanding of that is that when allocating an array, the new[] form will be picked. The only thing your example changes is the syntax; it doesn't make the language treat arrays as non-arrays (regular objects).

Upvotes: 6

Vlad from Moscow
Vlad from Moscow

Reputation: 310980

In this declaration

p_to_array p2 = new arr; // incompatible types 

type of initializer new arr; does not correspond to the type of variable p2

The type of initializer is int * that is the initializer is pointer to the initial element of the allocated array. The type of variable p2 is int (*p_to_array)[80] according to the typedef definition.

There is no implicit conversion from type int * to type int (*p_to_array)[80] . So the compiler issues an error.

The correct declaration could look for example the following way

p_to_array p2 = new arr[1];

Upvotes: 1

Related Questions