7

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;
}
3
  • 1
    That loss of information is called decay, and only works in one way. Commented Jan 12, 2015 at 11:58
  • Use vectors as they remember their size. Commented Jan 12, 2015 at 13:28
  • In recent versions of C++ you can use the array container class for fixed size collections. Commented Jan 12, 2015 at 15:28

3 Answers 3

6

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).

Sign up to request clarification or add additional context in comments.

2 Comments

What you quoted from cppreference is about the allocation function (operator new), which isn't really relevant because it returns void*. The relevant language feature is the new expression, specifically: "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.".
@interjay you're of course right. I've changed the quotation to refer to new expression.
4

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.

7 Comments

Thanks. Source? I don't think it would be nonsensical, the way I stumbled upon this was via link. Instead of casting you'd use double subscripting. This way information gets lost.
@bla Source for what? p[49] would be nonsensical. In fact, it would be presumably UB.
@bla he said where - [expr.new]/5. This refers to a section of C++ Programming Language Standard.
@BartekBanachewicz Just thought he referred to an explanation - the Standard doesn't. Might be one of those 'dusty corners'.
@bla Not really. What is your question exactly?
|
1

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];

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.