【问题标题】:C++ [] array operator with multiple arguments?C++ [] 具有多个参数的数组运算符?
【发布时间】:2010-12-28 12:40:43
【问题描述】:

我可以在 C++ 中定义一个接受多个参数的数组运算符吗?我试过这样:

const T& operator[](const int i, const int j, const int k) const{ 
    return m_cells[k*m_resSqr+j*m_res+i];
}

T& operator[](const int i, const int j, const int k){ 
    return m_cells[k*m_resSqr+j*m_res+i];       
}

但是我收到了这个错误:

error C2804 binary operator '[' has too many parameters

【问题讨论】:

    标签: c++ arrays operators operator-keyword


    【解决方案1】:

    编辑:正如评论中所指出的,在 C++20 中,运算符逗号将被弃用,如下面的答案。

    你不能重载operator[],但是你可以通过重载operator,来伪造它

    按照你的代码,它变成:

    T& operator,(const int i, const int j, const int k){ 
        return m_cells[k*m_resSqr+j*m_res+i];       
    }
    

    现在你可以打电话了

    something[1, 2, 3]
    

    您可以使用模板、带有可变参数的模板、std::pairstd::tuple 来扩展它,具体取决于您的用例和 C++ 版本

    【讨论】:

    【解决方案2】:

    为了完整起见:有一种方法可以实际使用带有多个参数的括号运算符,如果它们不是基本数据类型, 即通过重载逗号运算符而不是括号运算符,请参阅以下有关逗号重载的帖子:

    https://stackoverflow.com/a/18136340/5836981

    免责声明: 在我看来,重载逗号运算符很容易出错,并且会使代码更加晦涩难懂,只有在更奇特的情况下才值得考虑。我添加了这个答案,因为我在一些代码中遇到了这个实例,我花了一段时间才弄清楚关键不是 [] 运算符(不能用多个参数重载)而是 , 运算符。

    【讨论】:

    • 哇,我不知道你可以通过重载operator, 来在括号中包含多个参数,即天才/邪恶天才/可能是最可怕的想法。
    【解决方案3】:

    不,您不能重载operator[] 以接受多个参数。相反,您可以重载operator()。请参阅 C++ 常见问题解答中的 How do I create a subscript operator for a Matrix class?

    【讨论】:

      【解决方案4】:

      您可以使用 C++11 中提供的统一初始化语法来做一个不错的小技巧。您无需直接获取索引,而是使用 POD。

      struct indices
      {
        std::size_t i, j, k;
      };
      
      T& operator[](indices idx)
      {
        return m_cells[idx.k * m_resSqr + idx.j * m_res + idx.i];
      }
      

      然后使用新的语法:

      my_array<int> arr;
      // ...
      arr[{1, 2, 3}] = 42;
      

      【讨论】:

      • 您甚至不需要编写自己的结构;你可以使用std::arraystd::tuple
      • 如果您需要未知数量的参数,即使 std::initializer_list 也有效。它当然不适合这个精确的例子
      • @Justin:那引入大量代码。
      【解决方案5】:

      C++ 中任意类型和大小的 N 维数组:

      此答案的灵感来自 Pavel Radzivilovsky 的答案,谢谢。我很难实现实现,因为这是我第一次尝试递归模板。我想分享我所做的事情,以便其他人可以比我更快地理解。

      我编写了一个 c++ 模板类来创建一个任意类型和大小的 n 维数组。它需要用数组类型和维数来实例化。大小可以动态更改。我在下面给出了一个裸(剥离)工作版本,说明如何创建一个多维数组,其元素可以通过 operator[] 的连续应用来访问(例如 array[x][y] [z])。这个版本只能处理维度 n>1 的数组。 main函数以创建4维整数数组为例。

      编辑:请记住,为了便于阅读,下面的示例最小,因为它不会取消分配数组,也不会对访问进行边界检查。添加它是微不足道的,并留给程序员。

      #include <stdio.h>
      #include <stdlib.h>
      
      template <typename T, int N>
      struct array {
          array<T,N>() : data(NULL), offset((int*) malloc(sizeof(int)*N)){}
          array<T,N>(T *data, int *offset) : data(data), offset(offset){}
          array<T,N-1> operator[](int i){return array<T,N-1>(&data[i*offset[N]], offset);}
          bool resize(int *size){
              offset[N-1] = 1;
              int total_size = size[N-1];
              for(int i = N-2; i >= 0; i--){
                  total_size *= size[i];
                  offset[i] = offset[i+1]*size[i+1];
              }
              return (data = (T*) realloc (data, total_size*sizeof(T)));
          }
          T *data;
          int *offset;
      };
      
      template <typename T>
      struct array<T,1>{
          array<T,1>(T *data, int *offset) : data(data){}
          T& operator[](int i){return data[i];}
          T *data;
      };
      
      int main () {
          array<int, 4> a;
      
          // create array with dimensions [1][3][3][7]
          int size[4] = { 1, 3, 3, 7 };
          a.resize(size);               
      
          a[0][1][2][3] = 123;
      
          return 0;
      }
      

      享受吧。

      【讨论】:

      • 这很好,但我认为它被称为 array 并且在声明时看起来就像 std::array 但具有非常不同的模板参数(和语义)非常令人困惑(例如动态调整大小!)。考虑给它一个不同的名字。在 C 标头,mallocreallocfree 上也有很大的 ew ... 等一下 .... 你没有 free!你泄露了所有数据。不错。
      • @LightnessRacesinOrbit:我想我仍然欠你一个免费的析构函数:),但我也会觉得有责任捕获由任何越界访问引起的 seqfaults(例如在调整大小之前访问)。至于 C 标头.. 他们取代了我继续迷恋的接受者,即,我忠于我的根源:)
      • 然后 -1 用于向语言新手提供非常错误的代码和危险的建议。
      • 感谢 gospes 让这个小 perl 公开可用。 +1 用于教学示例和递归模板的巧妙使用。
      【解决方案6】:

      不可能重载[] 运算符以接受多个参数,但另一种方法是使用代理模式

      用两个词:a[x][y],第一个表达式 (a[x]) 将返回一个不同的类型,命名为代理类型,它将有另一个 operator[]。它会调用类似于原始类的_storedReferenceToOriginalObject-&gt;At(x,y)

      你将无法做到a[x,y],但我猜你还是想重载通常的 C++ 风格的 2D 数组语法。

      【讨论】:

      • @Neil Butterworth:我认为答案中隐含着“你做不到,但这里有一个替代方案”。
      • 我认为他想要将参数传递给 operator[](x,y) 的 C 二维数组语法 a[x][y],不是吗?这实际上是有道理的。
      • comp.lang.c++ 常见问题解答也解决了这个问题:parashift.com/c++-faq-lite/operator-overloading.html#faq-13.11
      • @jamesdlin 的常见问题链接现在是 isocpp.org/wiki/faq/operator-overloading#matrix-array-of-array“为什么我的 Matrix 类的界面不应该看起来像一个数组数组?”
      • 为什么不能做a[x, y]?逗号操作符很容易被重载,就像 Boost 所做的那样
      猜你喜欢
      • 1970-01-01
      • 2017-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      • 2012-11-08
      • 2017-11-14
      相关资源
      最近更新 更多