C++ 嵌套数组类型常量变量的副作用
我遇到了奇怪的副作用,我一点也不能向自己解释。可能我遗漏了一些非常明显的东西,但我已经查找了几个小时的bug,代码非常简单,所以我得出结论,我一定对…有一些基本的误解。。。什么 考虑这段代码,它是用来计算两个2d矩阵的乘积的(我更改了C++ 嵌套数组类型常量变量的副作用,c++,constants,side-effects,C++,Constants,Side Effects,我遇到了奇怪的副作用,我一点也不能向自己解释。可能我遗漏了一些非常明显的东西,但我已经查找了几个小时的bug,代码非常简单,所以我得出结论,我一定对…有一些基本的误解。。。什么 考虑这段代码,它是用来计算两个2d矩阵的乘积的(我更改了set()函数,将-1添加到参数单元格中,以使调试输出更易于理解 template<class T, unsigned column_count, unsigned row_count> class Matrix { private: const
set()
函数,将-1
添加到参数单元格中,以使调试输出更易于理解
template<class T, unsigned column_count, unsigned row_count>
class Matrix
{
private:
const static unsigned row_length = column_count;
const static unsigned column_length = row_count;
using matrix_type = std::array<std::array<T, row_length>, row_count>;
matrix_type matrix;
public:
using value_type = T;
Matrix(const matrix_type& matrix) : matrix(matrix) {}
Matrix() {}
friend std::ostream& operator<<(std::ostream& o, const Matrix& rhs)
{
for (unsigned i = 0; i < column_count; ++i) {
for (unsigned j = 0; j < row_count; ++j) {
o << rhs.matrix[i][j] << ' ';
}
o << '\n';
}
return o;
}
const auto& get_rows() const { return matrix; }
const auto get_columns() const
{
std::array<std::array<T, column_length>, column_count> columns;
for (unsigned i = 0; i < row_length; ++i) {
for (unsigned j = 0; j < column_length; ++j) {
columns[i][j] = matrix[j][i];
}
}
return columns;
}
void set(unsigned i, unsigned j, T v) { matrix[i][j] = -1; }
friend Matrix operator*(const Matrix& m1, const Matrix& m2)
{
auto columns = m1.get_columns();
auto rows = m2.get_rows();
Matrix m3;
std::cout << "before:"
<< "\n";
std::cout << m1 << "\n";
std::cout << m2 << "\n";
std::cout << m3 << "\n";
unsigned i{ 0 };
for (const auto& row : rows) {
i++;
unsigned j{ 0 };
for (const auto& column : columns) {
j++;
value_type v{ 0 };
for (unsigned k = 0; k < column.size(); ++k) {
v += row[k] * column[k];
}
m3.set(i, j, v);
}
}
std::cout << "after:"
<< "\n";
std::cout << m1 << "\n";
std::cout << m2 << "\n";
std::cout << m3 << "\n";
return m3;
}
};
现在我以不同的方式调用操作符*
:
matrix1*matrix2;
结果:
before:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
0 0 0
0 0 0
0 0 183238709
after:
-1 -1 -1
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
0 0 0
0 -1 -1
-1 -1 -1
before:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
0 0 0
0 0 0
0 0 -1823473620
after:
1 2 3
4 5 6
7 8 9
-1 -1 -1
4 5 6
7 8 9
0 0 0
0 -1 -1
-1 -1 -1
before:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
1385085408 32767 401515081
1 1385085440 32767
1385085440 32767 1385085464
after:
-1 -1 -1
4 5 6
7 8 9
-1 -1 -1
4 5 6
7 8 9
1385085408 32767 401515081
1 -1 -1
-1 -1 -1
matrix2*matrix1;
结果:
before:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
0 0 0
0 0 0
0 0 183238709
after:
-1 -1 -1
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
0 0 0
0 -1 -1
-1 -1 -1
before:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
0 0 0
0 0 0
0 0 -1823473620
after:
1 2 3
4 5 6
7 8 9
-1 -1 -1
4 5 6
7 8 9
0 0 0
0 -1 -1
-1 -1 -1
before:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
1385085408 32767 401515081
1 1385085440 32767
1385085440 32767 1385085464
after:
-1 -1 -1
4 5 6
7 8 9
-1 -1 -1
4 5 6
7 8 9
1385085408 32767 401515081
1 -1 -1
-1 -1 -1
matrix1*matrix1;
结果:
before:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
0 0 0
0 0 0
0 0 183238709
after:
-1 -1 -1
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
0 0 0
0 -1 -1
-1 -1 -1
before:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
0 0 0
0 0 0
0 0 -1823473620
after:
1 2 3
4 5 6
7 8 9
-1 -1 -1
4 5 6
7 8 9
0 0 0
0 -1 -1
-1 -1 -1
before:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
1385085408 32767 401515081
1 1385085440 32767
1385085440 32767 1385085464
after:
-1 -1 -1
4 5 6
7 8 9
-1 -1 -1
4 5 6
7 8 9
1385085408 32767 401515081
1 -1 -1
-1 -1 -1
如您所见,作为第一个参数传递的矩阵将被更改。这对我来说毫无意义,因为它是作为常量传递的,
set()
仅对m3
进行操作。不知何故,m3
部分“绑定”由于i
和j
都过早递增,因此在循环中写入超出范围的内容是因为i
和j
的第一个参数
代码应该如下所示:
for (const auto& row : rows) {
// i++;
unsigned j{ 0 };
for (const auto& column : columns) {
// j++;
value_type v{ 0 };
for (unsigned k = 0; k < column.size(); ++k) {
v += row[k] * column[k];
}
m3.set(i, j, v);
j++; // <--
}
i++; // <--
}
for(常量自动&行:行){
//i++;
无符号j{0};
用于(常量自动和列:列){
//j++;
值_类型v{0};
for(无符号k=0;k j++;//是的,但我仍然不知道变异来自何处,正如set()
只为m3
调用,而m1
经历了变异。请构造一个。虽然是FWIW,但我不能在这里重新编程:对我来说,这看起来像是一个常见的错误,投票关闭。我可以自己关闭它吗?哈哈,谢谢。我知道这会是一件愚蠢的事情。