Alright, I've been defining a templated Matrix class with some basic matrix ops and I've noticed some strange behaviour when implementing the operator*
typedefunsignedint matsize_t;
template <class T, matsize_t M, matsize_t N>
class Matrix
{
public:
Matrix();
Matrix(const Matrix& other);
virtual ~Matrix();
T & operator()(matsize_t row, matsize_t col);
const T & operator()(matsize_t row, matsize_t col) const;
std::string str() const;
matsize_t numRows() const;
matsize_t numCols() const;
private:
T* data;
};
template <class T, matsize_t M, matsize_t N>
Matrix<T, M, N>::Matrix()
: data(0)
{
data = new T[M * N];
for (matsize_t i = 0; i < M; ++i)
{
for (matsize_t j = 0; j < N; ++j)
{
(*this)(i, j) = T();
}
}
}
template <class T, matsize_t M, matsize_t N>
inline T& Matrix<T, M, N>::operator ()(matsize_t row, matsize_t col)
{
return data[row * N + col];
}
Some Global Functions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
template <class T, matsize_t M, matsize_t N, matsize_t P>
Matrix<T, M, P> operator*(const Matrix<T, M, N>& lhs, const Matrix<T, N, P>& rhs)
{
Matrix<T, M, P> result;
for (int i = 0; i < M; ++i)
{
for (int j = 0; j < P; ++j)
{
result(i, j) = T();
for (int k = 0; k < N; ++k)
{
result(i, j) += (lhs(i, k) * rhs(k, j));
}
}
}
return result;
}
What's strange is that if I remove the line which assigns result(i, j) = T(), my result matrix is totally messed. But I thought that when an array is allocated on the heap (inside the constructor of the Matrix class), the default constructor of the array element is called. So, in my tests, it's int() that's getting called, which initializes to zero (which I've verified using (T() == 0). However unless I manually zero it again (not including when I manually zero it during the constructor) using result(i, j) = T() I get incorrect results. It just doesn't make any sense to me at all.
Am I missing some fine detail or is this a compiler bug?
int a=int() is a synonym of int a=0. However, that's just a bit of syntactical sugar. In reality, built-in types do not have constructors. Therefore, class members and array elements that are of built-in types are left uninitialized unless explicitly initialized by the user.
This doesn't apply to elements in standard containers.
Ok, but in Matrix<T, M, N>::Matrix(); I'm manually iterating through the data array and initializing with (*this)(i, j) = T();. However, in myoperator* unless I reinitialize that variable using result(i, j) = T(); (which just writes over the old value with the "same" value again0, I get incorrect results returned in my result Matrix. Which is why I'm confused.
I just installed Visual C++ 2010 Express Edition to test the code with a different compiler, and it works fine with or without the result(i, j) = T(); statement now.
EDIT: Found it...turns out there was some heap corruption that didn't crash in GCC but did in Visual C++. After I fixed it, it works exactly the same using both compilers.