我创建了一个类矩阵,除具有一些成员函数外,运算符和构造函数还具有两个变量:
int m,它是二次矩阵的尺寸(边长)
double a [],其中包含矩阵的元素。
只要我只创建一个矩阵对象A似乎都可以正常工作,并且我的所有成员运算符和函数都可以正常工作。
我的问题是,一旦我创建了类矩阵的第二个对象B,对象A的变量也会随之改变。
相关代码如下:
class Matrix{
private:
const int m;
double a[];
public:
Matrix(int inpm);
void fillMatrix(const double inpa[]);
};
Matrix::Matrix(int inpm): m(inpm){
a[impm*inpm];
}
void Matrix::fillmatrix(const double inpa[]){
for (int i ; i<m*m ; i++){
a[i]=inpa[i];
}
}
int min =2;
double ain[min*min] = {1,2,3,4};
double bin[min*min] = {5,6,7,8};
Matrix A(min);
Matrix B(min);
A.fillMatrix(ain);
//A looks precisely as it should here:
//m=2, a={1,2,3,4}
B.fillMatrix(bin);
//Here B looks as it should but A has changed to:
//m=0, a={7,8,3,4}
当我为第二个对象运行fillMatrix()时,显然会发生第一个对象的更改,但是我无法弄清楚原因,尤其是因为m是一个常数整数。
真的很感谢所有帮助。
PS:我使用另一个成员函数“ void printMatrix();”使用std:cout查看m的值以及a中的所有元素。
答案 0 :(得分:3)
a[impm*inpm];
这并不符合您的想法。 GCC
甚至警告statement has no effect
。
a
在这里仍未初始化,尝试访问a[i]
class Matrix{
private:
const int m;
double *a;
....
和
Matrix::Matrix(int inpm): m(inpm)
{
a = new double[inpm*inpm];
}
然后记住要delete
Matrix::~Matrix()
{
delete a;
}
答案 1 :(得分:3)
c++
数组实际上是不允许变量的。有plenty of sources about why variable length arrays (vla's) are not allowed。如果您不需要在运行时选择大小的动态长度数组,则需要分配一些内存:
double *a;
...
a = new double[inpm*inpm];
但这太糟了!现在,您必须记住正确删除和访问所有内容。您可以将此内存包装在一个类中以控制它,并且由于这是一个好主意,因此c ++将此作为标准提供。它称为std::vector
。您的代码会很高兴地简化为:
class Matrix{
private:
const int m;
std::vector<double> a;
public:
Matrix(int inpm) : m(inpm), a(m * m) {}
答案 2 :(得分:0)
我注意到您的代码存在一些问题。其他人(例如您的成员double a[];
)已经提到了前几个,这是未初始化的,并且C ++不允许使用可变长度向量。为了解决这个问题,我将在稍后讨论两种可能的解决方案。其他人提到的另一个问题是,在Matrix::fillMatrix()
函数中,for循环i
中的变量也未初始化,因此i
可以是任何东西,这将导致不确定的行为。
其他人未提及的一些问题如下:
在构造函数定义中,您尝试使用m
初始化a[impm*inpm]
,我认为这可能是您的错字。另一个是将函数声明为::fillMatrix()
,但在类声明之外将其定义为::fillmatrix()
。同样,我认为这可能只是您的错字。
对于上述在C++
中使用数组的问题,最简单的方法是其他人已经说过的,那就是使用std::vector<type>
。
另一种方法是编写一个与std::vector
类似但具有矩阵机制的类。使用模板,您的类看起来像这样:如果要在运行时使用可变长度的容器,则必须在使用模板时知道其大小,在这里使用模板会有所帮助,因为必须在实例化时在编译时推导出模板!
template<class T, unsigned N>
class Matrix {
private:
static const unsigned Stride = N;
static const unsigned Size = Stride * Stride;
T data[Size] = {};
public:
Matrix() {};
void fillMatrix( const T* dataIn );
void printMatrix();
};
template<class T, unsigned N>
void Matrix<T, N>::fillMatrix( const T* dataIn ) {
for( unsigned int i = 0; i < Size; i++ ) {
this->data[i] = dataIn[i];
}
}
template<class T, unsigned N>
void Matrix<T, N>::printMatrix() {
for( unsigned int i = 0; i < Stride; i++ ) {
for( unsigned int j = 0; j < Stride; j++ ) {
std::cout << this->data[i*Stride + j] << " ";
}
std::cout << '\n';
}
}
int main() {
// 2x2 = 4
double ain[4] = { 1,2,3,4 };
double bin[4] = { 5,6,7,8 };
Matrix<double, 2> A;
Matrix<double, 2> B;
A.fillMatrix( ain );
A.printMatrix();
std::cout << '\n';
B.fillMatrix( bin );
B.printMatrix();
std::cout << '\n';
// test A again
A.printMatrix();
std::cout << '\n';
B.printMatrix();
std::cout << '\n';
// Try it with other types
// 3x3 = 9
char data[9] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' };
Matrix<char, 3> C;
C.fillMatrix( data );
C.printMatrix();
std::cout << '\n';
return 0;
}
输出:
1 2
3 4
5 6
7 8
1 2
3 4
5 6
7 8
a b c
d e f
g h i
使用模板进行这种类型的设计时,您不仅限于仅使用type
,int
等单个float
,甚至可以使用User Defined Types
。您唯一需要考虑的是您可能拥有的任何operators
类型。同样,编写此类的方式将始终创建一个MxM
矩阵,该矩阵将始终是一个正方形矩阵。如果您需要一个非方阵;您可以通过向模板参数列表中添加2 nd 无符号常量值并将其相应地重命名为MxN
来添加此类。然后只需替换它们在数学中的位置即可。看起来像这样:
template<class T, unsigned M, unsigned N>
class Matrix {
private:
static const unsigned Row = M;
static const unsigned Col = N;
static const unsigned Size = Row * Col;
T data[Size] = {};
};
现在如何标记它们可能取决于您想要Row-Col
专业还是Col-Row
专业...
答案 3 :(得分:0)
问题是由于您的数组声明。人们过去将这种数组声明称为“灵活数组声明”。而且它不会按您预期的那样工作。另外,使用灵活数组时要遵循某些规则。 但是,如果要创建动态数组,可以使用malloc动态创建数组。