Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will the new expression ever return a pointer to an array?

In this excellent answer by AndreyT, he explains that in C, when a function needs an array whose dimension is known at compile-time, it's a major technique-level error to declare

void process_array(int *ptr, size_t plen);

instead of

void process_array(int (*arr_ptr)[10]);

Furthermore, he opines that many programmers are oblivious to the second option and know only about the first. One of the reasons, he writes, for this behaviour is when an array needs to be dynamically allocated and passed to the second version, programmers don't know how to do it; they're so accustomed to int *p = malloc(sizeof(*p) * 10) which returns an int *. In C, the way to do it is, as he shows

int (*arr_ptr) [10] = malloc(sizeof(*arr_ptr));

This got me thinking on how one would do the same in C++. I know we've std::array, std::vector, etc. but I'm interested in understanding new's usage. So I tried doing this:

typedef int Array10[10];
Array10 *p = new Array10;    // error: cannot convert ‘int*’ to ‘int (*)[10]’

When I change p's type to int* the compiler (GCC 4.8.1) is happy. I looked up C++11 standard (draft n3337, §5.3.4/5) to understand this further, it says:

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. [Note: both new int and new int[10] have type int* and the type of new int[i][10] is int (*)[10]end note]

I understand that new int [10] is in action; what I get back should be freed using delete [] p and not delete p. However what I need seems to be the latter, where the allocation is not an array of integers but an array itself, as a single/whole object.

Is there a way to do it? Or my trying to do this in itself shows a misunderstanding of the C++ type system? Or it is right but is simply not allowed by the standard?


Aside: When a function takes an array whose size is fixed, as in option 2, IMHO the best thing to do for the calling function is to declare an automatic array instead of resorting to dynamically allocating one and worrying about clean-up.

like image 916
legends2k Avatar asked Oct 19 '13 15:10

legends2k


People also ask

Can a function return a pointer to an array?

C programming does not allow to return an entire array as an argument to a function. However, you can return a pointer to an array by specifying the array's name without an index.

Does new in C++ return a pointer?

Once initialization is complete, enough information is present for the allocated storage to be an object. Returns a pointer to the object(s) of a pointer type derived from new-type-id or type-id . The program uses this pointer to access the newly allocated object.

Can a pointer be stored in an array?

int (*ptr)[10]; Here ptr is pointer that can point to an array of 10 integers. Since subscript have higher precedence than indirection, it is necessary to enclose the indirection operator and pointer name inside parentheses. Here the type of ptr is 'pointer to an array of 10 integers'.

Can a pointer act as an array?

Technically speaking, an array name never acts as a pointer. An expression with array type (which could be an array name) will convert to a pointer anytime an array type is not legal, but a pointer type is. And the declaration of an array as a function parameter is converted into a declaration of a pointer.


1 Answers

Yes, in fact it is suggested in the standard text you quoted:

int (*arr_ptr)[10] = new int[1][10];

The pointer returned by the new-expression has type int (*)[10], i.e. pointer to array of 10 ints. You need delete[] to delete it.

like image 188
M.M Avatar answered Oct 18 '22 08:10

M.M