如何使用new在堆上创建一个自动数组[N]

3

关于指针和数组,我有一个特殊情况。

我该如何在堆上分配一个固定大小的(自动)数组?让我们直接看代码以了解我的问题:

typedef int ArrayOf10Ints[10];

int f()
{
        ArrayOf10Ints * p = new ArrayOf10Ints; // Error: cannot initialize a variable of type 'ArrayOf10Ints *'
                                               // (aka 'int (*)[10]') with an rvalue of type 'int *'

        ArrayOf10Ints * q = new ArrayOf10Ints[1] // OK: allocates space for 10 ints

        delete q; // Warning: use delete []
}

为什么分配表达式p不起作用?为什么rvalue是一个int*而不是一个ArrayOf10Ints*?为什么q可以工作?
注意:我的目标是理解分配pq的意外行为。正如其他人指出的那样,有许多直接的方法来解决这个问题。例如,在我的情况下,我使用指针来表示数组是可选的——它可能存在也可能不存在——所以我会这样做:
boost::optional<std::array<int, 10> > optional_array;

2
不需要!使用标准容器即可。 - πάντα ῥεῖ
3
尝试给p分配内存时,出现错误提示“无法将'int*'转换为'int (*) [10]'进行初始化”。由于你定义了类型为ArrayOfTenInts,它是指向由10个整数(40位数据类型)组成的内存区域的指针,因此类型为int*。此外,这个链接可能会有帮助:https://dev59.com/Tm855IYBdhLWcg3wHwiH。 - Polb
具体使用 std::array<int,10> - πάντα ῥεῖ
1
注意:出于本讨论之外的原因,我需要完全按照这样做。请说明限制的详细内容,您实际上不能更改哪些部分?是typedef吗? - πάντα ῥεῖ
另外请注意,我们这里不进行“讨论”。Stack Overflow 不是一个论坛。 - πάντα ῥεῖ
你说得对,我已经编辑了我的问题以澄清我的意图,并让其他读者明确知道有更好的解决方案来满足我的需求。 - alexc
2个回答

3
这是new的一种行为,有些令人惊讶。尽管ArrayOf10Intsint[10]的别名,但当您在new表达式中使用它时,结果就像您编写了new int[10]一样。

这在[expr.new]/5中有规定。

当分配的对象是数组(即使用语法或或表示数组类型时),产生指向数组的初始元素(如果有)的指针。

因此在您的示例中,new表达式返回一个int *,因此出现了错误。

解决方法是执行您所展示的操作。

ArrayOf10Ints* q = new ArrayOf10Ints[1];
delete[] q;

将数组放到一个结构体中,或使用std::array。请注意,即使你写下:
```c++ int arr[10]; ```
在内存中仍会分配10个int的空间。如果您需要将该数组传递给函数,请使用指针或引用,以避免复制整个数组。
int* p = new ArrayOf10Ints;

在这种情况下,你必须使用delete[] p,因为operator new[]也会被调用。

演示


0
注意:由于本讨论之外的原因,我需要确切地执行此操作。
当然不行,因为错误的事情是行不通的。
使用 std::array<int,10> 代替。这段代码应该可以顺利运行:
typedef array<int,10> ArrayOf10Ints;

int f() {
     ArrayOf10Ints * p = new ArrayOf10Ints;
     // ...

     delete p;
}

然而,我不建议您自己管理newdelete,除非您绝对确定需要这样做。


相信我,如果可以的话,我会使用boost::optional<std::array<int, 10>>。 - alexc
1
@alexc 如果你没有访问当前的 c++11 标准,可以自己编写 std::array 模板的版本,这非常直截了当和简单。如果你正在使用 Turbo C++ 这样的东西,那你已经没有任何希望了。 - πάντα ῥεῖ
这不仅仅是潜在的老编译器的问题。我正在处理一个系统,我不能做出这样的改变。我的目标是要理解为什么p不起作用而q可以。 - alexc
1
@alexc 到底有哪些变化呢?typedef 是由遗留代码预定义的,你需要利用它吗? - πάντα ῥεῖ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接