【问题标题】:How can I get a two-dimension array that stored in an one-dimension array through overload the function call operator in C++?如何通过重载C++中的函数调用运算符来获得存储在一维数组中的二维数组?
【发布时间】:2020-11-27 09:13:23
【问题描述】:

我在空闲时间编写一个小型科学计算库。而且我发现有人说将二维数组存储在一维数组中更快,您可以通过重载函数全部运算符来做到这一点。但是不知道怎么处理。

现在我认为函数数组应该这样做:

#include<iostream>
int main(){
    int M=10;
    int N=10;
    double x[M*N];
    cout<<x(m,n)<<endl;//print the m*N+n element of x
    return 0;
}

我该怎么办?或者任何地方都说过。我在stackoverflow中看不到它......

x[m*N+n] 对于二维条件很有用。但是如果我是四维的话,就是x[m*A+n*B+p*C+l*D],每次用的时候都会写一个长段...

【问题讨论】:

  • 正确的拼写是:dimension
  • 正确的数组访问是x[m*N + n]
  • 但是如果我有更多的维度,那就麻烦了。我可以通过重载函数调用运算符吗?@paddy

标签: c++ arrays class operator-overloading scientific-computing


【解决方案1】:

好的,我承认您想编写一个科学计算库,并且(低级)优化很重要。这是我不只是说的唯一原因:不要担心低级数组,只使用向量的向量 [of vectors...]

但是VLA 数组不是 C++ 的东西。它是一个(记录在案的)gcc 扩展,也受 Clang 支持,但其他编译器将无法正确编译 double x[M*N];,并且只保留一个 0 字节数组,除非 MN 是编译时常量(constexpr)。

即使对于科学图书馆来说,干净的x[i][j] 相对于x[i*M + j] 的开销也是微不足道的。除非您可以通过分析证明它既是必需的又是有效的,否则不要这样做。

话虽如此,如果您必须处理动态大小的多维数组,则习语x(i,j) 会很有用。我曾经尝试使用标准的[] 表示法为它构建一个通用库,它导致nightmare

你需要:

  • 为适当尺寸托管动态大小数组的类(您可以使用基于尺寸编号的模板)

  • 一个大小沿所有维度分配底层一维数组的 ctor - 我建议使用向量,除非您想明确处理复制/移动构造/分配的极端情况(规则 5)

  • operator()(int i, int j, ...) 的实现,具有正确数量的刚刚返回的维度(对于维度 K、L、M、N 和坐标 i、j、k、l):

      x[l + K * (k + L * (j + M * i))]
    

【讨论】:

    【解决方案2】:

    这就是你要找的吗? Matrix1D 类有一个一维向量,但模拟一个二维矩阵,并允许您使用 () 运算符来访问它。

    您可以通过修改 operator(...) 和 set(...) 函数将其扩展到任意多个维度。

    #include <iostream>
    #include <vector>
    
    class Matrix1D {
     private:
      std::vector<double> x;
      int N;
    
     public:
      Matrix1D(int m, int n) {
        this->x = std::vector<double>(m * n);
        this->N = n;
      }
    
      double operator()(int m, int n) { return this->x[m * this->N + n]; }
    
      void set(int m, int n, double v) { this->x[m * this->N + n] = v; }
    };
    
    int main() {
      Matrix1D c1(5, 5);
      c1.set(3, 2, 1);
      std::cout << c1(3, 2) << "\n";
    }
    

    【讨论】:

      【解决方案3】:

      在 C++ 中,运算符必须是类成员。因此,为了提供函数调用重载,您首先需要为您的数组创建一个自定义类。

      class oneDimArray {
          private:
             unsigned int lines;
             unsigned int columns;
      
             // You can replace the number with the maxim size of array desired
             // be it another number or integer constant.
             double x[100]{0};
           
          public:
             
             // Overloading the class constructor to accept 2D Arrays
             oneDimArray(double [][100] matrix) {
                 
                 // Getting the number of lines and columns
                 lines = sizeof matrix / sizeof matrix[0];
                 columns = sizeof[0] matrix / sizeof(double);
      
                 // Setting the elements
                 for(unsigned i = 0; i < lines*columns; i++) {
                    x[i] = matrix[i / columns][i % columns];
                 }
             }
      
             // Finally overloading the function call operator
             double operator() (unsigned int line, unsigned int column) {
                 return x[line * lines + column];
             }
      };
              
      

      在此之后,您所要做的就是创建该类的一个对象(您的实际数组)并对其进行初始化:

      oneDimArray myArray = oneDimArray( someMatrix );
      
      // Using the overloaded operator to access elements
      myArray(1, 2);
      

      以下可以扩展到任何类型的数组。此外,如果您为输入 ( >> ) 运算符提供重载,您将能够直接读取它。

      【讨论】:

      • 您的答案与已经给出的答案相同。请考虑投票,而不是两次给出相同的答案。
      猜你喜欢
      • 2016-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多