【问题标题】:What is the proper way to assign to an array inside a C++ class?在 C++ 类中分配给数组的正确方法是什么?
【发布时间】:2019-03-20 00:58:18
【问题描述】:

我有这个 C++ 类矩阵(参见下面的代码片段)。

在我的随机化方法中,我设置了 matr 的所有值(matr 是一个 2x2 矩阵)。

当我调用 print_matrix 时,它会复制元素 (1,0) 和 (1,1) 并将它们都打印两次,以及不打印 (0,0) 或 (0,1)。

我做错了什么?

查看下面的输出。

class Matrix {

public:


    int rows;
    int cols;
    double rnd;

    double* matr;

    Matrix(int a, int b) {

        printf(" vals %d %d \n", a, b);

        rows = a;
        cols = b;

        matr = new double[a, b];
        //this->print_matrix();
        //clear_matrix();
        //this->print_matrix();
        //this->randomize();
        //this->print_matrix();

    }



    double &at(int pos1, int pos2) {


        return matr[pos1, pos2];
    };

    void setPos(int pos1, int pos2, double value) {
        matr[pos1, pos2] = value;
    };

    void randomize() {

        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                rnd = double(rand()) / double((RAND_MAX)+1.0);
                printf("Rand : %d, C: %d, Val: %f \n",r,c, rnd);
                this->setPos(r, c, rnd);
                //matr[r, c] = rnd;
                printf("New value R: %d C: %d Val: %f \n", r, c, matr[r,c]);
                //rnd = 0;
            }
        }
    };

    void subtract_Scalar(double val) {
        double curr_Val = 0;
        double result = 0;
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                curr_Val = this->at(r, c);
                result = curr_Val - val;
                this->setPos(r, c, 0);
                this->setPos(r, c, (float)result);
                //this->setPos(r, c, 5);
                //printf("SS CV : %f, Re: %f  \n", curr_Val, result);
                curr_Val = 0;
                result = 0;
            }
        }
    };

    void print_matrix() {
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                printf("PM R : %d, C: %d Val: %f \n", r, c, matr[r,c]);
                //printf("%f", this->at(r, c));
            }
            //printf("\n");
        }
    }



    void clear_matrix() {
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {

                this->setPos(r, c, 0.0);
            }
        }
    }

    };

【问题讨论】:

  • 您在matr = new double[a, b] 中使用的语法与您在 C++ 中声明或访问二维数组的方式不同。听起来你可以使用good C++ book
  • 这还能编译吗?
  • @Ayxan 逗号操作符可以隐藏很多错误
  • @Ayxan 它确实可以编译。这也是我的第一个 C++ 程序...
  • @MattWard 从那里找到一个好的可靠的来源学习。 C++ 不是一种你应该尝试“随便学习”的语言

标签: c++ oop matrix


【解决方案1】:

由于以下行,您的程序具有未定义的行为:

printf("PM R : %d, C: %d Val: %f \n", r, c, matr[r,c]);

matr[r,c] 不访问矩阵的元素。由于逗号运算符,它只是matr[c],其计算结果为指针。您正在使用%f 打印指针。那是未定义的行为部分。您需要使用matr[r][c] 来访问矩阵的元素。

printf("PM R : %d, C: %d Val: %f \n", r, c, matr[r][c]);

matr[r, c] 的使用不正确。

更多详情请参阅the documentation of the comma operator


更新

感谢@PeteBecker 敏锐的眼光,问题与我最初想的不同。

事实证明,matr 的类型是 double*。因此,matr[c] 的计算结果为双精度值。因此,该程序没有未定义的行为。它只访问c——matr 的元素,无论r 的值如何。

问题开始于:

matr = new double[a, b];

应该是的

matr = new double[a * b];

使用matr[r, c] 访问矩阵元素的任何位置都必须是matr[r*cols + c]

at,你需要使用:

return matr[pos1 * cols + pos2];

setPos,你需要使用:

matr[pos1 * cols + pos2] = value;

randomize,你需要使用:

printf("New value R: %d C: %d Val: %f \n", r, c, matr[r*cols + c]);

print_matrix,你需要使用:

printf("PM R : %d, C: %d Val: %f \n", r, c, matr[r*cols + c]);

您可以通过为constconst 对象提供at 重载来简化访问元素的代码。

double& at(int r, int c) { return matr[r*cols + c]; }
double at(int r, int c) const { return matr[r*cols + c]; }

那么,setPos 可以实现为:

  void setPos(int pos1, int pos2, double value) {
     at(pos1, pos2) = value;
  };

printf 行可以更新为:

printf("New value R: %d C: %d Val: %f \n", r, c, at(r, c));
printf("PM R : %d, C: %d Val: %f \n", r, c, at(r, c));

【讨论】:

  • 为什么matr[r,c] 被评估为matr[c]?你能详细说明一下吗?
  • 为了以后的参考,我把它留在这里:“在逗号表达式E1, E2中,表达式E1被评估,它的结果被丢弃(虽然如果它有类类型,它不会' t 被销毁,直到包含的完整表达式结束),并且它的副作用在表达式 E2 的评估开始之前完成“
  • 嗯,matr[c]double。它不是故意的,但自始至终都是一致的。 matr 的类型是 double*,它指向 double 数组的第一个元素。所有的数组操作最终都会这样对待它。
  • @PeteBecker,很遗憾直到你敏锐的眼睛才注意到差异。
猜你喜欢
  • 1970-01-01
  • 2011-07-19
  • 1970-01-01
  • 2011-03-28
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
  • 2017-01-25
相关资源
最近更新 更多