简体   繁体   English

是否可以在C ++中动态创建恒定大小的数组?

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

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++. 是否有任何有效的语法,或者在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);

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

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] . 您无法执行此操作的原因是, new int[3]已经完全分配了您想要的东西,即int[3]类型的对象。 It's just that what the new-expression returns , is a pointer to its first element. 只是new-expression 返回的是指向其第一个元素的指针。 5.3.4/1: 5.3.4 / 1:

If the entity is a non-array object, the new-expression returns a pointer to the object created. 如果实体是非数组对象,则new-expression返回指向创建的对象的指针。 If it is an array, the new-expression returns a pointer to the initial element of the array. 如果它是一个数组,则new-expression返回一个指向数组初始元素的指针。

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). 我猜想解决此问题的方法是将reinterpret_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 . 我想这是道德的,如果您编写的模板天真地用new分配了一些未知类型T ,那么当有人将数组类型作为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. 您将把它分配给错误的指针类型,如果您对此进行了修复(也许使用auto ),则会错误地删除它。

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

You could always use boost::array, which will be in C++0x. 您可以始终使用boost :: array,它将在C ++ 0x中使用。 Otherwise, any solution will be awkward at best: arrays are broken in C, and C++ maintains compatilibity with C in this respect. 否则,任何解决方案充其量都是尴尬的:数组在C中被破坏,并且C ++在这方面保持与C的兼容性。 Fred Overflow offered one solution; Fred Overflow提供了一种解决方案。 even easier (but syntactically noisy) would be to wrap the array in a struct: struct A { int arr[3]; 甚至更容易(但在语法上比较嘈杂)是将数组包装在struct中:struct A {int arr [3]; }; }; and allocate and manipulate this. 并分配和操纵它。

You just do 你只是做

int *p = new unsigned int [3]

You can then use *p as a pointer or an array ie *(p+1) or p[1] 然后,您可以将*p用作指针或数组,即*(p+1) or p[1]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM