对于二维矩阵,它在 C++11 中的函数是否与 C11 中的函数类似

Is it a similar function in C++11 as in C11 for the twodimensional matrix?

本文关键字:函数 是否 C11 于二维 它在 C++11      更新时间:2023-10-16

我注意到在 gcc C11 中您可以将任何矩阵传递给函数fn(int row, int col, int array[row][col])。如何将我在 C11 中的以下放置(链接到另一个堆栈溢出答案(程序转换为 C++11 中的程序?

C - 在函数中分配矩阵

如您所见,我可以在 C11 中将静态和动态分配数组传递给函数。在 C++11 中可能吗?

我基于不同的堆栈溢出答案制作了一个示例程序,但是所有函数都适用于 array1,而它们都不适用于 array2,其中 double array1[ROW][COL] = { { } }auto array2 = new double[ROW][COL]()

如何像在 C11 fn(int row, int col, int array[row][col]) 中那样为两个数组创建一个函数?

#include <iostream>
#include <utility>
#include <type_traits>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;
const int ROW=2;
const int COL=2;
template <size_t row, size_t col>
void process_2d_array_template(double (&array)[row][col])
{
    cout << __func__ << endl;
    for (size_t i = 0; i < row; ++i)
    {
        cout << i << ": ";
        for (size_t j = 0; j < col; ++j)
            cout << array[i][j] << 't';
        cout << endl;
    }
}
void process_2d_array_pointer(double (*array)[ROW][COL])
{
    cout << __func__ << endl;
    for (size_t i = 0; i < ROW; ++i)
    {
        cout << i << ": ";
        for (size_t j = 0; j < COL; ++j)
            cout << (*array)[i][j] << 't';
        cout << endl;
    }
}
// int array[][10] is just fancy notation for the same thing
void process_2d_array(double (*array)[COL], size_t row)
{
    cout << __func__ << endl;
    for (size_t i = 0; i < row; ++i)
    {
        cout << i << ": ";
        for (size_t j = 0; j < COL; ++j)
            cout << array[i][j] << 't';
        cout << endl;
    }
}
// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(double **array, size_t row, size_t col)
{
    cout << __func__ << endl;
    for (size_t i = 0; i < row; ++i)
    {
        cout << i << ": ";
        for (size_t j = 0; j < col; ++j)
            cout << array[i][j] << 't';
        cout << endl;
    }
}
int main()
{
    double array1[ROW][COL] = { { } };
    process_2d_array_template(array1);
    process_2d_array_pointer(&array1);    // <-- notice the unusual usage of addressof (&) operator on an array
    process_2d_array(array1, ROW);
    // works since a's first dimension decays into a pointer thereby becoming int (*)[COL]
    double *b[ROW];  // surrogate
    for (size_t i = 0; i < ROW; ++i)
    {
        b[i] = array1[i];
    }
    process_pointer_2_pointer(b, ROW, COL);

    // allocate (with initialization by parentheses () )
    auto array2 = new double[ROW][COL]();
    // pollute the memory
    array2[0][0] = 2;
    array2[1][0] = 3;
    array2[0][1] = 4;
    array2[1][1] = 5;
    // show the memory is initialized
    for(int r = 0; r < ROW; r++)
    {
        for(int c = 0; c < COL; c++)
            cout << array2[r][c] << " ";
        cout << endl;
    }
    //process_2d_array_pointer(array2);
    //process_pointer_2_pointer(array2,2,2);
    int info;
    cout << abi::__cxa_demangle(typeid(array1).name(),0,0,&info) << endl;
    cout << abi::__cxa_demangle(typeid(array2).name(),0,0,&info) << endl;
    return 0;
}

您在 C11 中使用的功能是在 C99 中引入的,专门设计用于允许高效轻松地处理多维数组。

虽然C++在(多维(数组方面与 C 共享基本语法,但数组类型在C++中的能力要小得多:C++数组类型的大小需要是编译时常量。以下是一些示例:

void foo(int a, int b) {
    int foo[2][3];     //legal C++, 2 and 3 are constant
    int bar[a][3];     //Not C++, proposed for C++17: first dimension of an array may be variable
    int baz[a][b];     //Not C++, legal in C99
    int (*fooPtr)[2][3];    //legal C++
    int (*barPtr)[a][3];    //Not C++, legal in C99
    int (*bazPtr)[a][b];    //Not C++, legal in C99
    typedef int (*fooType)[2][3];    //legal C++
    typedef int (*barType)[a][3];    //Not C++, legal in C99
    typedef int (*bazType)[a][b];    //Not C++, legal in C99
    int (*dynamicFoo)[3] = new int[2][3];    //legal C++
    int (*dynamicBar)[3] = new int[a][3];    //legal C++
    int (*dynamicBar)[b] = new int[a][b];    //Not C++
}

如您所见,在 C 语言中,动态大小数组的几乎所有可能的事情在C++中都是不可能的。即使是为下一个C++标准提出的VLA扩展也没有多大帮助:它仅限于数组的第一维。

在C++中,您必须使用std::vector<>来实现 C99 可变长度数组可以实现的目标。所有后果:

  • std::vector<std::vector<> >中的数据在内存中不是连续的。您的缓存可能不喜欢这样。

  • std::vector<std::vector<> >不能保证所有线性阵列具有相同的长度。这可能有用,也可能很痛苦,具体取决于您的用例。

  • 如果您有对std::vector<std::vector<> >中的元素的迭代器,则无法将其前进到下一行中的相应元素。

C++没有

VLA。它被提议用于 C++17,但还有很多工作要做,因为它对类型系统来说是一个相当大的变化,无论如何,使用 C 样式数组在C++都是不受欢迎的。

如您所发现的,当编译时大小已知时,您可以使用模板。如果在编译时不知道大小,那么最好的办法是使用包装在类中的一维vector以您想要访问它的方式访问它。

当然,vectorsvector也是可能的;它描述了一个交错数组。您是否更喜欢单个大内存块取决于各种因素(编码的复杂性、运行时速度/内存使用注意事项等(。