Is it possible to dynamically create an array of c

2020-02-01 01:07发布

问题:

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

回答1:

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>();
}


回答2:

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


回答3:

You could always use boost::array, which will be in C++0x. Otherwise, any solution will be awkward at best: arrays are broken in C, and C++ maintains compatilibity with C in this respect. Fred Overflow offered one solution; even easier (but syntactically noisy) would be to wrap the array in a struct: struct A { int arr[3]; }; and allocate and manipulate this.



回答4:

You just do

int *p = new unsigned int [3]

You can then use *p as a pointer or an array i.e. *(p+1) or p[1]