【问题标题】:Is it possible to dynamically create an array of constant size in C++?是否可以在 C++ 中动态创建一个恒定大小的数组?
【发布时间】:2023-04-09 10:38:01
【问题描述】:

首先,我想向大家保证,我问这个问题是出于好奇。我的意思是,不要告诉我如果我需要这个,那么我的设计就有问题,因为我在实际代码中不需要它。希望我说服了你 :) 现在问题来了:

对于大多数类型 T 我们可以写

T* p = new T;

现在如果 T 是一个数组类型呢?

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

我试过了:

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

但这不起作用。

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

编辑:我猜我不够清楚。我希望能够在这种情况下使用它:

void f(int(&)[3]);
int (*p)[3] = new ???;
f(*p);

【问题讨论】:

  • 如果我理解正确,您想知道 C++ 是否有办法“推断”数组的大小,而无需在分配中明确指定它?

标签: c++ arrays new-operator


【解决方案1】:

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

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

【讨论】:

  • 嗯...不太符合我的预期,但我的示例肯定会起作用...+1
【解决方案2】:

你不能这样做的原因是new int[3] 已经准确地分配了你想要的东西,一个int[3] 类型的对象。只是新表达式返回是一个指向它的第一个元素的指针。 5.3.4/1:

如果实体是非数组对象, new 表达式返回一个指针 到创建的对象。如果它是一个 数组,新表达式返回一个 指向初始元素的指针 数组。

返回一个指向第一个元素的指针使得 3 在运行时之前是未知的,所以我想通过提前知道它,你已经绊倒了你没有使用的灵活性。

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

[编辑:呃,是的,或者 FredOverflow 的想法,它没有缺点,但需要使用 delete[] 而不是 delete。]

我想道德是,如果您编写的模板天真地分配了一些未知类型 Tnew,那么当有人将数组类型传递为 T 时,该模板将不起作用。您会将其分配给错误的指针类型,如果您修复它(可能使用auto),您将错误地删除它。

编辑回答 j_kubik 的问题:

这是区分数组和非数组类型的一种方法。如果你写一个这样的函数,它返回一个包含指针并能够正确删除它的对象,那么你就有一个通用的 new/delete 用于任何类型的 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>();
}

【讨论】:

  • new int[3]new int[1][3] 都必须通过 delete[] 发布。
  • @FredOverflow:确实,我的意思是“而不是”非数组类型会发生什么。如果我正在发明 Armen 想要的魔法不存在的语法,分配数组类型的单个对象 就好像 它是一个非数组类型,那么它会让你用delete 删除它通过从MagicNew 返回的相同指针。所以它看起来像typedef int arr[3]; arr *p = MagicNew arr; delete p;。我知道他没有在他的问题中具体说明这一点,也许我认为其他人会以同样的方式发明它是错误的。
  • 总结一下 - 有没有办法让新删除模板为数组类型做好准备,还是根本不可能?
  • @J_kubik:我认为你可以做到,但你需要区分T 是否是数组类型。我会在我的答案中添加一种方法。
【解决方案3】:

你总是可以使用 boost::array,它将在 C++0x 中。 否则,任何解决方案充其量都是尴尬的:数组是 在 C 中中断,并且 C++ 在此保持与 C 的兼容性 尊重。 Fred Overflow 提供了一种解决方案。更容易(但 语法上嘈杂)将数组包装在一个结构中: 结构 A { int arr[3]; }; 并分配和操作它。

【讨论】:

  • 这将是一种解决方法,而不是解决方案 :) @Fred's 也是如此,但至少我的示例适用于他的解决方法。用你的,它不会,不是吗?
  • 包装器是一种解决方法,但 boost:array 将是我使用固定大小数组的首选解决方案。如此奇怪但可能: void f(array& p);数组* p = 新数组; f(*p);
【解决方案4】:

你就是这样做

int *p = new unsigned int [3]

然后您可以将*p 用作指针或数组,即*(p+1) or p[1]

【讨论】:

  • 对不起,但这不是我要问的。完全没有
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
  • 1970-01-01
  • 2018-03-17
  • 2019-01-16
  • 2021-03-09
  • 1970-01-01
  • 2014-05-23
相关资源
最近更新 更多