如何在平面和多维数组之间进行转换而不复制数据?

时间:2019-06-19 09:24:10

标签: c++ arrays multidimensional-array

我有一些结构化为多维数组的数据,即double[][],我需要将其传递给一个函数,该函数需要一个double[]的线性数组以及用于多维表示。

例如,我可能有一个3 x 5多维数组,我需要将其作为15个元素的平面数组以及height和width参数一起传递,以便函数知道它是3x5数组而不是5x3数组。

然后该函数将返回一个平面数组和大小元数据,我需要使用它来将数据转换回多维类型。

我认为平面和多维表示形式在内存中的数据布局完全相同;唯一的区别是如何执行索引操作。因此,我想通过类型转换进行“转换”,而不是复制数组值。

在总大小相同的多维数组和平面数组之间进行类型转换的最正确,最易读的方法是什么?

我实际上知道在编译时多维数组的维数是多少。数组大小不是动态的。

4 个答案:

答案 0 :(得分:2)

@Maxim Egorushkin和@ypnos:double *flat = &multi[0][0];给出了最正确的方法。它可以与任何不错的编译器一起正常工作。但不幸的是,这不是有效的C ++代码,它会调用未定义的行为。

问题在于,对于数组double multi[N][M];NM是编译时常量表达式),&multi[0][0]是数组的第一个元素的地址大小M。因此,仅对M进行指针算术运算是合法的。有关更多详细信息,请参见其他question of mine

答案 1 :(得分:1)

我认为最受欢迎的方法是:

create table lt (id1 int, val1 string); insert into lt VALUES (1, "one"), (2, "two"), (3, "three"); create table rt (id2 int, val2 string); insert into rt VALUES (2, "two"), (3, "three"), (4, "four"); select * from lt left join rt on id1=id2; +-----+-------+------+-------+ | id1 | val1 | id2 | val2 | +-----+-------+------+-------+ | 1 | one | NULL | NULL | | 2 | two | 2 | two | | 3 | three | 3 | three | +-----+-------+------+-------+

这就是在C中完成的过程,并且您确实可以使用简单的C数组进行操作。

您还可以在用例(编译时已知的尺寸)中查看select lt.*, NULL as id2, NULL as val2 from lt where id1 not in (select id2 from rt) union all select * from lt join rt on id1=id2; +-----+-------+------+-------+ | id1 | val1 | id2 | val2 | +-----+-------+------+-------+ | 1 | one | NULL | NULL | | 2 | two | 2 | two | | 3 | three | 3 | three | +-----+-------+------+-------+ ,但是它不是多维的,因此,如果将其级联,将会失去连续的布局。

答案 2 :(得分:1)

  

在总大小相同的多维数组和平面数组之间进行类型转换的最正确,最易读的方法是什么?

第一个数组元素的地址与数组的地址一致。您可以传递第一个元素的地址,而无需强制转换。

答案 3 :(得分:0)

您可以使用强制转换为对数组的引用。这需要使用一些奇特的C ++类型语法,但作为回报,它允许使用对数组有效的所有功能,例如每个循环。

#include <iostream>

using namespace std;

int main()
{
    static constexpr size_t x = 5, y = 3;
    unsigned multiArray[x][y];
    for (size_t i = 0; i != x; ++i)
        for (size_t j = 0; j != y; ++j)
            multiArray[i][j] = i * j;

    static constexpr size_t z = x * y;
    unsigned (&singleArray)[z] = (unsigned (&)[z])multiArray[0][0];
    for (const unsigned value : singleArray)
        cout << value << ' ';
    cout << endl;

    return 0;
}

请注意,这种和其他基于强制类型转换的方法仅适用于实际的多维数组。如果它是一个数组数组(例如unsigned **multiArray;),则不会在连续的内存块中分配它,并且强制转换无法绕过它。