是否可以在c++中动态地创建一个常量大小的数组?

时间:2022-08-24 21:20:57

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,我们可以写

T* p = new T;

now what if T is an array type?

如果T是数组类型呢?

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

是否有任何有效的语法,或者在c++中是不可能的。如果不可能,那为什么呢?谢谢

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

4 个解决方案

#1


10  

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:

不能这样做的原因是新的int[3]已经分配了您想要的对象,类型为int[3]的对象。新表达式返回的是指向第一个元素的指针。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.

返回一个指向第一个元素的指针是允许3在运行时之前未知的,所以我假设通过提前知道它,您已经在不使用的灵活性上犯了错误。

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

我想解决这个问题的方法是重新解释t_cast回您想要的指针类型(不一定是可移植的),或者分配一个包含int[3]的结构体(并使用指向其数据成员的指针)。

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

[编辑:嗯,是的,或者FredOverflow的想法,它没有缺点,但是需要使用delete[]而不是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.

我想,如果你写模板,天真地分配一些未知类型T和新的,那么模板不会工作当有人通过一个数组类型为T .你会将它分配给错误的指针类型,如果你修复与汽车(可能),你会错误地删除它。

Edit in answer to j_kubik's question:

编辑回答j_kubik的问题:

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.

这里有一种区分数组和非数组类型的方法。如果您编写这样的函数,它返回一个对象,该对象保存指针并能够正确地删除它,那么对于任何类型的T,您都有一个通用的new/delete。

#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


11  

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

要从new获取指向数组的指针,必须动态分配一个二维数组:

int (*p)[3] = new int[1][3];

#3


2  

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.

您可以使用boost:::array,它将在c++ 0x中。否则,任何解决方案都将是笨拙的:数组在C中被破坏,在这方面c++与C保持了兼容性。Fred Overflow提供了一个解决方案;更简单的(但语法上有干扰)是将数组包装成一个struct: struct a {int arr[3];};分配和操作这个。

#4


-2  

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]

然后可以使用*p作为指针或数组,例如*(p+1)或p[1]

#1


10  

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:

不能这样做的原因是新的int[3]已经分配了您想要的对象,类型为int[3]的对象。新表达式返回的是指向第一个元素的指针。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.

返回一个指向第一个元素的指针是允许3在运行时之前未知的,所以我假设通过提前知道它,您已经在不使用的灵活性上犯了错误。

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

我想解决这个问题的方法是重新解释t_cast回您想要的指针类型(不一定是可移植的),或者分配一个包含int[3]的结构体(并使用指向其数据成员的指针)。

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

[编辑:嗯,是的,或者FredOverflow的想法,它没有缺点,但是需要使用delete[]而不是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.

我想,如果你写模板,天真地分配一些未知类型T和新的,那么模板不会工作当有人通过一个数组类型为T .你会将它分配给错误的指针类型,如果你修复与汽车(可能),你会错误地删除它。

Edit in answer to j_kubik's question:

编辑回答j_kubik的问题:

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.

这里有一种区分数组和非数组类型的方法。如果您编写这样的函数,它返回一个对象,该对象保存指针并能够正确地删除它,那么对于任何类型的T,您都有一个通用的new/delete。

#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


11  

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

要从new获取指向数组的指针,必须动态分配一个二维数组:

int (*p)[3] = new int[1][3];

#3


2  

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.

您可以使用boost:::array,它将在c++ 0x中。否则,任何解决方案都将是笨拙的:数组在C中被破坏,在这方面c++与C保持了兼容性。Fred Overflow提供了一个解决方案;更简单的(但语法上有干扰)是将数组包装成一个struct: struct a {int arr[3];};分配和操作这个。

#4


-2  

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]

然后可以使用*p作为指针或数组,例如*(p+1)或p[1]