有没有一种方法将指针转换为数组类型?

13

C++中的C数组在语法上有些难以理解,需要花费一些时间去适应。尽管一个一维数组会衰变为一个指针:

void fn1(int x[2]) {}
void fn2(int*x) {}

fn1()fn2()具有相同的函数签名。

实际上,数组确实有一种类型,其中包括数组中有多少个元素,例如:

void fn(int (&)[2]) {}

fn() 只会接受一个包含2个整数元素的数组。

问题在于,我只能看到带有该签名的堆栈、文件作用域或结构/类分配生成的固定元素数量的数组:

int twoElementArray[2];

如果我要在堆上动态分配它,似乎无法获得相同的签名。我想我可能可以进行类型转换,但没有成功:

int (&array)[2] = reinterpret_cast<int(&)[2]>(new int[2]); // FAIL!
有没有任何想法可以实现这一点(如果可能的话)?
编辑:虽然我选择了一个答案,但它实际上并没有进行任何强制转换,而是使用了一种绝对更好的方法来进行操作(在我看来,如果不需要强制转换,最好不要进行强制转换)。但是,从技术上讲,它并没有回答问题,因为问题问是否“有一种将指针强制转换为数组类型的方法?” 答案是肯定的。
int (&array)[2] = *reinterpret_cast<int(*)[2]>(new int[2]); // SUCCESS!

请注意,我不一定推荐这样做,但它确实回答了问题。如果我需要将指针转换为数组类型,那么就应该这样做。阅读选定的答案,了解在使用operator new[]时更好的解决方案。


你可以使用模板并定义一个整型常量 FIXED_SIZE = 2。 - Ariel Pinchover
@Infested:抱歉,我不明白你的意思。你能再解释一下并且加上一个例子吗? - Adrian
如果fn1只接受固定大小的数组,则可以将其制作为模板函数,它应该获取两个参数,int []和int FIXED_SIZE = 2,然后您可以有int x [FIXED_SIZE]。 - Ariel Pinchover
@Infested:fn1()是我对于C++数组工作原理的解释中的一部分,面向那些不熟悉该语言的人。是的,我可以这样写:void fn3(int* array, size_t FIXED_SIZE) {}或者另外这样写:void fn3(int[] array, size_t FIXED_SIZE) {} 这是一个普遍的解决方法。然而,我试图利用类型系统防止数组与其大小脱钩。 - Adrian
你尝试过使用 int [] x 吗? - Ariel Pinchover
显示剩余4条评论
3个回答

10

如果我正确理解了您的问题,您想要做的事情类似于这样:

// allocate an array of one int[2] dynamically
// and store a pointer to it
int(*p)[2] = new int[1][2];

// now initialize a reference to it
int(&array)[2] = *p;

// delete the array once you no longer need it
delete[] p;

1

我认为这就是你要找的。对于堆,一个二维数组 int[M][N] 会转化为 int(*)[N]。如果想以引用的方式传递它,需要解引用它(参见下面的 m):

#include <iostream>
using namespace std;

void func(int (&x)[2])
{
    cout << x[0] << ' ' << x[1] << endl;
}

int main()
{
    // on the heap
    auto m = new int[1][2];
    m[0][0] = 1; m[0][1] = 2;
    auto n = new int[1][3];
    n[0][0] = 4; n[0][1] = 5; n[0][2] = 6;

    // on the stack
    int o[2] = {7,8};
    int p[3] = {9,10};

    func(*m);
    //func(*n); // doesn't compile, wrong size
    func(o);
    //func(p); // doesn't compile, wrong size
}

输出:

1 2
7 8

+1 如果使用正确的术语“衰减”。我已经更正了我的问题,使用相同的术语。 - Adrian

-1

根据Mark的回答,这个可能更好:

template <typename T>
void func(const T &x)
{
    cout << x[0] << ' ' << x[1] << endl;
}

唯一的坏处是这段代码是有效的:

cout << x[3] << endl;

抱歉,这个答案是错误的。你刚刚创建了一个接受任何类型的const引用的模板函数。它根本不接受数组。去尝试编译一下吧。你可能想要的是类似于template <typename T> void func(const T (&x)[2]) {...}或者template <typename T, size_t N> typename std::enable_if<(N>=2)>::type func(const T (&x)[N]) {...}。然而,这也假设我想要接受任何类型而不仅仅是int,这并不是问题所要求的。 - Adrian

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