能否将动态分配的数组传递给需要数组引用的函数?

5

提前说明:我知道在这里要求你做的事情并不是一个好主意。这只是出于一种病态的语言好奇心所产生的问题,并非实际使用需要。我在这里应用的规则完全是任意的。

假设我们有一个函数,其精确定义如下。不能将其更改为除此以外的任何东西,不能使用模板或函数重载。该函数的实现也不能更改(可以视为未知),但是我们知道参数被用作输出参数。

void my_func(int (&arr)[10]);

在另一个函数中,我们动态分配了一个数组。 这个分配也不能改变,我们不允许在栈上分配。 也不允许进行进一步的分配。
int* my_arr = new int[10];

有没有可能以某种方式调用my_func并传递my_arr?换句话说,有没有办法欺骗类型系统,使其将my_arr视为数组而不是指针?

朴素的转换无法解决问题,它们都导致编译错误:

my_func((int[10])my_arr);
my_func(static_cast<int[10]>(my_arr));
my_func(reinterpret_cast<int[10]>(my_arr));

另一点说明:我想欺骗类型系统。我不想从堆栈数组等处复制数据。为什么?再次强调:出于病态好奇心。

2个回答

5
您可以使用 reinterpret_cast 来实现此操作。为了使代码更易于阅读,您可以使用数组类型的别名来表示以下内容:
void my_func(int (&arr)[10])
{
    for (auto e : arr)
        std::cout << e << " ";
}

int main()
{
    using array_t = int[10];
    int* my_arr = new int[10]{1,2,3,4,5,6,7,8,9,10};
    my_func(reinterpret_cast<array_t&>(*my_arr));
}

你可以在这个实时示例中看到它的工作。


有趣!不过我很惊讶 my_func(reinterpret_cast<(int[10])&>(*my_arr)); 不起作用。这个别名似乎不仅更容易阅读,而且在技术上也是必需的。为什么呢? - Brotcrunsher
2
@Brotcrunsher 这不是必需的,但它会让生活变得更容易。数组的语法有点复杂,所以要获取对数组的引用,你需要使用 int(&)[10],类型中的 (&) 告诉编译器 & 或者引用应用于 int[10]。使用 int&[10] 是行不通的,因为那将是一个引用的数组,这是不允许的。(int[10])& 也不起作用,因为就 C++ 语法而言,它是错误的。 - NathanOliver

2

虽然我不建议做任何这样的事情...

#include <iostream>

void my_func(int (&arr)[10])
{
    std::cout << "Address: " << &arr << std::endl;
    for (int i=0; i<10; ++i)
        std::cout << arr[i] << std::endl;
}

int main()
{
    int *ptr=new int[10];

    for (int i=0; i<10; ++i)
        ptr[i]=i;
    std::cout << "Pointer: " << ptr << std::endl;
    my_func(*( int (*)[10])ptr);
    return 0;
}

不要使用 C 风格的转换,reinterpret_cast 也可以工作。关键是先获取指向数组的指针,然后对其进行解引用。就这样,一个数组的引用。


哦,哇!实际上,( int (*)[10]) 中的 (*) 有点让我困惑。你能解释一下它的作用吗?为什么( int*[10]) 不起作用? - Brotcrunsher
1
前者是一个指向十个整数数组的指针。后者是一个包含十个指向整数的指针的数组。这也是为什么如果你想先将AB相加再将结果乘以C,需要使用(A+B)*C运算符,而A+B*C不能实现该操作。 - Sam Varshavchik

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