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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.