在C++中将值输入到2D矩阵时使用+=

ckocjqey  于 2023-07-01  发布在  其他
关注(0)|答案(1)|浏览(125)

我正在编写2个矩阵的矩阵乘法代码,大小为n1,n2n2,n3
这就是我所尝试的:

#include <climits>
#include <iostream>
using namespace std;

int main() {
    int n1 = 3;
    int n2 = 3;
    int n3 = 3;
    
    int arr1[n1][n2] = {
        {1, 2, 3},
        {5, 6, 7},
        {9, 10, 11}
    };
    int arr2[n2][n3] = {
        {2, 0, 0},
        {0, 2, 0},
        {0, 0, 2}
    };
    int res[n1][n3];

    for (int c = 0; c < n3; c++) {
        for (int r = 0; r < n1; r++) {
            for (int i = 0; i < n2; i++) {
                res[r][c] += arr1[r][i] * arr2[i][c];  // This is the main part
            }
        }
    }

    for (int i = 0; i < n1; i++) {
        for (int j = 0; j < n3; j++) {
            cout << res[i][j] << ' ';
        }
        cout << endl;
    }

    return 0;
}

输出为:

6422058 1877910233 1878006934 
1878000406 20 7022734 
7022746 68 22

然后,我尝试更改具有+=的行:

int res[n1][n3];

for(int c = 0; c < n3; c++){
    for(int r = 0; r < n1; r++){
        int val = 0;
        for(int i = 0; i < n2; i++){
            val += arr1[r][i] * arr2[i][c];    // Here I used new variable val
        }
        res[r][c] = val;
    }
}

问题消失了。输出:

2 4 6 
10 12 14 
18 20 22

为什么这解决了问题?

kmpatx3s

kmpatx3s1#

问题是,上线了:

int res[n1][n3];

res中的所有内存都是不确定的,而不是零。这就是为什么打印出如此荒谬和巨大的数值。这是代码中“未定义行为”的症状。

int val = 0;
for(int i=0; i < n2; i++){
    val += arr1[r][i] * arr2[i][c];    // Here I used new variable val
}
res[r][c] = val;

这就修复了它,因为您从val = 0开始,然后添加到它,并将结果写入res[r][c],所以这里没有未定义的行为。但是,您也可以只写:

int res[n1][n3] {};
// or
int res[n1][n3] = {};
// or
int res[n1][n3] = {0}; // C-compatible

...在顶部,这将初始化res中的所有元素为零。所有这些都做同样的事情。

关于VLA的说明

所有数组都是Variable Length Arrays (VLAs),这在C++中是不允许的。您必须将其大小设置为constexpr,或至少const才能解决此问题:

constexpr int n1 = 3;
constexpr int n2 = 3;
constexpr int n3 = 3;

您的代码只会编译,因为编译器支持将VLA作为非标准扩展。

相关问题