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