我的问题是:为什么我的功能GetNumberOfRows()
和GetNumberOfColumns()
不返回构造函数中指定的值?
我有一个类模板,该模板可以为 std::vector
分配存储的内存。作为此类的私人成员,我有行的数量和列数(mNumRows
,mNumCols
(。我有一个构造函数,该构造函数将行数和列作为参数,并创建一个std::vector
来存储值。我创建了断言,以确保当我索引时,矩阵时,索引不得超过行的数量或列的数量。当超载 * - 操作器时,我断言矩阵列和向量大小是相同的(将矩阵类乘以矢量类时(。我的程序编译了,但是在执行程序期间,我一直遇到断言错误,因此我检查了mNumRows
和mNumCols
的值,即使我指定它们在构造函数中为2和2,也证明为31和0。
我的程序在指定mNumRows
和mNumCols
是同类中的数字时给出了正确的结果,但是我希望能够在主文件中指定它。我提供了指定课程的标题文件。
template<typename T> class Matrix
{
private:
std::vector<T> mData; // entries of matrix
int mNumRows;
int mNumCols; // dimensions
int N;
public:
// copy constructor
Matrix(const Matrix& otherMatrix)
{
mNumRows = otherMatrix.mNumRows;
mNumCols = otherMatrix.mNumCols;
std::vector<T> mData;
for (int i = 0; i < otherMatrix.N; i++)
{
mData = otherMatrix.mData;
}
}
// Storing matrix as a flattened matrix
// And using std::vector
Matrix(int numRows, int numCols)
{
assert(numRows > 0);
assert(numCols > 0);
int mNumRows = numRows;
int mNumCols = numCols;
int N = mNumRows * mNumCols;
for (int i = 0; i < N; i++)
{
mData.push_back(0.0);
}
}
~Matrix()
{
mData.clear();
}
int GetNumberOfRows() const
{
return mNumRows;
}
int GetNumberOfColumns() const
{
return mNumCols;
}
};
在我写的主文件中。
Matrix mat(2, 2);
std::cout << mat.GetNumberOfRows() << ", " << mat.GetNumberOfColumns() << std::endl;
mat.~Matrix();
输出为31、0。应该为2、2。为什么行和列会更改?
问题是因为构造函数中的这三行:
int mNumRows = numRows;
int mNumCols = numCols; // Corrected from question which had assignment from numRows
int N = mNumRows * mNumCols;
他们定义了三个 new 和本地变量,它们与同名成员变量无关。当构造函数函数结束时,这些本地变量的所有更改将丢失。
一种解决方案是对成员变量使用普通分配:
mNumRows = numRows;
mNumCols = numCols;
N = mNumRows * mNumCols;
但我建议您了解构造函数初始化器列表您可以在其中直接初始化成员变量:
Matrix(int numRows, int numCols)
: mNumRows(numRows), mNumCols(numCols), N(mNumRows * mNumCols)
{
// The rest of the constructor...
}
您在复制构建器中遇到了相同的问题,其中定义了一个新的本地变量mData
,该变量会阴影同名的成员变量。
有了对std::vector
构造函数的了解,您根本不需要构造函数函数中的任何内容,都可以使用构造函数初始器列表进行初始化:
Matrix(int numRows, int numCols)
: mData(numRows * numCols), mNumRows(numRows), mNumCols(numCols)
{
// Totally empty!
}
请注意,我不初始化N
。那是因为它不需要,您可以通过其size
函数从向量获得N
的值。
还请注意,我没有为向量内容的内容指定默认值。那是因为值将被默认结构。对于简单类型(例如int
或float
(,这意味着值将为零。
类定义完全没有意义。
例如,考虑以下复制构造函数。
Matrix(const Matrix& otherMatrix)
{
mNumRows = otherMatrix.mNumRows;
mNumCols = otherMatrix.mNumCols;
std::vector<T> mData;
for (int i = 0; i < otherMatrix.N; i++)
{
mData = otherMatrix.mData;
}
}
有声明为本地cector
std::vector<T> mData;
被称为类的相应数据成员。
然后在循环中
for (int i = 0; i < otherMatrix.N; i++)
{
mData = otherMatrix.mData;
}
局部向量n时间由vector elesermatrix.mdata分配。
在此构造函数中
Matrix(int numRows, int numCols)
{
assert(numRows > 0);
assert(numCols > 0);
int mNumRows = numRows;
int mNumCols = numRows;
int N = mNumRows * mNumCols;
for (int i = 0; i < N; i++)
{
mData.push_back(0.0);
}
}
也有使用的本地变量,而不是类的相应数据成员
int mNumRows = numRows;
int mNumCols = numRows;
此外,还有一个错字
int mNumCols = numRows;
^^^^^^^
这个构造函数可以看起来像
Matrix(int numRows, int numCols)
: mData( numRows * numCols ), mNumRows( numRows ), mNumCols( numCols ), N( numRows * numCols )
{
assert(numRows > 0);
assert(numCols > 0);
}
也是一个坏主意
mat.~Matrix();
这可能导致不确定的行为。
这是一个示范性程序,显示如何重写您的代码
#include <iostream>
#include <vector>
template<typename T = int>
class Matrix
{
private:
size_t mNumRows;
size_t mNumCols; // dimensions
size_t N;
std::vector<T> mData; // entries of matrix
public:
// copy constructor
Matrix( const Matrix &otherMatrix )
: mNumRows( otherMatrix.mNumRows ),
mNumCols( otherMatrix.mNumCols ),
N( otherMatrix.mNumRows * otherMatrix.mNumCols ),
mData( otherMatrix.mData )
{
}
// Storing matrix as a flattened matrix
// And using std::vector
Matrix( size_t numRows, size_t numCols )
: mNumRows( numRows ),
mNumCols( numCols ),
N( numRows * numCols ),
mData( N )
{
}
~Matrix() = default;
size_t GetNumberOfRows() const
{
return mNumRows;
}
size_t GetNumberOfColumns() const
{
return mNumCols;
}
};
int main()
{
Matrix<> mat(2, 2);
std::cout << mat.GetNumberOfRows() << ", " << mat.GetNumberOfColumns() << std::endl;
}
程序输出是
2, 2