8

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.

8
  • a better highlight in that standards quote is denotes an array type, which explains your Array10 test Commented Oct 19, 2013 at 16:25
  • @Cubbi: Haha... perhaps. I've faithfully formatted it as-is in the document i.e. whatever is in boldface and italics are from the standard and the emphasis isn't mine. Commented Oct 19, 2013 at 16:26
  • The answer is in the text you quoted: int(*p)[10] = new int[1][10]; You could also do this: int(*p)[10] = reinterpret_cast<int(*)[10]>(::operator new(sizeof(int[10]))); Commented Oct 19, 2013 at 17:28
  • @jrok: but that seems to be a hack to me; with multidimensional array and reinterpret_cast. Dunno, may be it's not a hack. Commented Oct 20, 2013 at 5:28
  • 1
    Not an exact duplicate of the question, but Charles Bailey's answer fully answers this question Commented Sep 25, 2014 at 1:35

2 Answers 2

1

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.

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

4 Comments

+1 Not what I asked, but close. It doesn't return just a pointer to an array, it returns a pointer to the first element of an array of pointer to an array, hence one can't delete it, but only delete [] it.
It does return a pointer to an array, it doesn't return a pointer to "the first element of an array of pointer to an array". The latter would be new (int (*[5])[5]). It does require [] to delete , as you say.
Had it been int [2][10] wouldn't it still return int (*) [10] which is nothing but the pointer to the first element of an array of (array of 10 ints). Just that the count is 1 in the previous case, but still an array of one element, thus one has to use delete [].
Yes that's right. The first element of "array of array of 10 ints" is an array of 10 ints. Also, any object can be considered as an array of 1 element of whatever type it is.
0

If I have understood correctly what you want then you can use std::array. For example

{
    typedef std::array<int, 10> Array10;

    Array10 *p = new Array10;
    delete p;
}

3 Comments

No. I've clearly stated in the question that there're workarounds using the standard C++ library, but I want to do it using the language grammar only, not its library facilities. It's more on the lines of understanding the C++ type system.
@legends2k the thing to understand here is not the C++ type system (well - that is useful but not the key issue); the key issue is with the syntax for new. Doing new some-array-type gets you a pointer to the first element of an array with that type, whereas new non-array-type gets you a pointer to the whole object of non-array-type.
Yes, I agree, it's the syntax of new that should be inspected and not type system in general here. Agree to the next point as well.

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.