重载函数调用 operator() 用于模板对象的索引和赋值

Overloading function call operator () for indexing and assignments of a template object

我正在尝试为矩阵数据结构创建一个模板,我希望有一种简洁直观的方式来索引和分配元素(即 'A(i,j)' return 一个元素和 'A(i,j)=x' 给这个元素赋值。)

根据其他论坛帖子,我看到通过引用 return 数组元素,function/operator 可以 return 并以这种方式更改该元素。

template <typename T, int Rows, int Cols>
    struct Matrix {
        private:
        public:
            const int rows = Rows; //number of rows
            const int cols = Cols; //number of columns
            T data[Rows*Cols];     //contents of matrix

            //Single element indexing and assigment
            T& operator() (int i, int j) {
                return data[ (i-1)*(this->cols) + j ];
            }
    };

int main(){
    const int m = 3;
    const int n = 4;
    Matrix<float, m, n> A;

    for (int i = 0; i < A.rows; i++) {
        for (int j = 0; j < A.cols; j++) {
            A(i,j) = 3.14;
        }
    }

    return 0;
}

当我尝试使用显式类型的结构(在本例中为 int)而不是模板时,这非常有效,但是现在我使用的是模板,赋值 'A(i,j) = x' 具有修改索引的效果'i' 和 'j' 通常会破坏循环并导致分段错误。

有谁知道为什么会这样,如果我可以做些什么来达到预期的结果?

我是 c++ 的新手,所以如果我反对该语言的最佳实践,请随时告诉我

用于索引 data 的公式不正确。

始终将您的函数更新为 return data[0],但打印索引。输出将清楚地表明您没有使用正确的索引。

T& operator() (int i, int j) {
    int index = (i-1)*(this->cols) + j;
    std::cout << "Index: " << index << std::endl;
    
    return data[0];  // This is wrong but that's not the
                     // purpose of this suggested change.
}

有用link:How to debug small programs

PS 正确的索引是i*(this->cols) + j.

the assignment A(i,j) = x has the effect of modifying the indices i and j which usually breaks the loops and causes segmentation faults.

if I print i and j directly before and after A(i,j) = 3.14; the values change in ways that aren't clear to me. For instance after the first call, j changes from 0 to 1078523331

这意味着你正在破坏记忆。写入一个 超出范围 的数组元素将执行此操作。

您的数组是从 0 开始索引的。您的 ij 变量从 0 开始。但是您要从 i 值中减去 -1。那么,当您尝试在计算中使用 (i-1) 来获取数组索引时,您认为会发生什么?

好吧,让我们找出答案 - 您尝试访问的第一个元素是 A(0,0),因此:

  data[ (i-1)*(this->cols) + j ]
= data[ (0-1)*(4) + 0 ]
= data[ (-1)*(4) + 0 ]
= data[ -4 + 0 ]
= data[ -4 ]

索引-4处没有数组元素!您正在返回对位于 data[] 数组 前 4*sizeof(T) 字节 的内存的引用。

要解决此问题,您需要将计算更改为:

(i * this->cols) + j

现在,A(0,0)(以及所有其他输入 0 <= i < rows0 <= j < cols)的结果将是正确的:

  data[ (i * this->cols) + j ]
= data[ (0 * 4) + 0 ]
= data[ 0 + 0 ]
= data[ 0 ]