Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to dynamically create an array of constant size in C++?

First of all, I want to reassure you all that I am asking this question out of curiosity. I mean, don't tell me that if I need this then my design has problems because I don't need this in real code. Hope I convinced you :) Now to the question:

For most types T we can write

T* p = new T;

now what if T is an array type?

int (*p)[3] =  new ???; //pointer to array of 3 = new ???

I tried this:

typedef int arr[3];
arr* p = new arr;

but this doesn't work.

Is there any valid syntax for this or it is impossible in C++. If it is impossible, then why? Thanks

Edit: i am guessing I wasn't clear enough. I want to be able to use it in this situation:

void f(int(&)[3]);
int (*p)[3] = new ???;
f(*p);
like image 834
Armen Tsirunyan Avatar asked Mar 17 '11 13:03

Armen Tsirunyan


People also ask

Can you make a dynamic array in C?

We can create an array of pointers also dynamically using a double pointer. Once we have an array pointers allocated dynamically, we can dynamically allocate memory and for every row like method 2.

Can we declare an array without assigning the size of an array in C?

C does not support arrays with a dynamic number of elements. The number of elements of an array must be determined either at compile time or since C99 can be evaluated at runtime at the point of creation. Once the array is created, its size is fixed and cannot be changed.

Can I provide array size dynamically?

A dynamic array is an array with a big improvement: automatic resizing. One limitation of arrays is that they're fixed size, meaning you need to specify the number of elements your array will hold ahead of time. A dynamic array expands as you add more elements. So you don't need to determine the size ahead of time.


2 Answers

To get a pointer to an array from new, you have to dynamically allocate a two-dimensional array:

int (*p)[3] = new int[1][3];
like image 118
fredoverflow Avatar answered Sep 28 '22 01:09

fredoverflow


The reason you can't do it is that new int[3] already allocates exactly what you want, an object of type int[3]. It's just that what the new-expression returns, is a pointer to its first element. 5.3.4/1:

If the entity is a non-array object, the new-expression returns a pointer to the object created. If it is an array, the new-expression returns a pointer to the initial element of the array.

Returning a pointer to the first element is what allows the 3 to be unknown until runtime, so I suppose that by knowing it in advance, you've tripped over flexibility that you aren't using.

I guess the ways around this are to reinterpret_cast back to the pointer type you want (not necessarily portable), or to allocate a struct containing an int[3] (and use a pointer to its data member).

[Edit: er, yeah, or FredOverflow's idea, which has neither disadvantage, but requires use of delete[] instead of delete.]

I guess the moral is, if you write templates that naively allocate some unknown type T with new, then the template won't work when someone passes an array type as T. You'll be assigning it to the wrong pointer type, and if you fix that (perhaps with auto), you'll be deleting it wrongly.

Edit in answer to j_kubik's question:

Here's one way to distinguish between array and non-array types. If you write a function like this, that returns an object that holds the pointer and is capable of correctly deleting it, then you have a generic new/delete for any type T.

#include <iostream>

template <typename T>
void make_thing_helper(T *) {
    std::cout << "plain version\n";
}

template <typename T, int N>
void make_thing_helper(T (*)[N]) {
    std::cout << "array version\n";
}

template <typename T>
void make_thing() {
    make_thing_helper((T*)0);
}

int main() {
    typedef int T1;
    typedef int T2[3];
    make_thing<T1>();
    make_thing<T2>();
}
like image 35
Steve Jessop Avatar answered Sep 27 '22 23:09

Steve Jessop