Help with vector inside a class

Started by
3 comments, last by Zael 15 years ago
I am trying to implement a matrix class which contains a 2D vector and has methods for matrix operations in the class. At the moment I am having issue with either the initialization or the output function, and I am unsure as to which. The problem that is occurring is that at run-time I am getting output of differing values when as near as I can tell they should all be the same. The weirdest part is that when I run the code in a function outside of the class this problem goes away. Below is my code and output. Matrix.h

#ifndef _Matrix
#define _Matrix
#include <iostream>
#include <vector>

template <class T>
class Matrix
{
	private:
	std::vector <std::vector <T> > mat;

	public:
	Matrix(unsigned int, unsigned int, T);
	unsigned int rows();
	unsigned int cols();
	T operator () (unsigned int row, unsigned int col);
};

template <class T>
Matrix<T>::Matrix(unsigned int cols, unsigned int rows, T values)
{
	T x=values;
	mat.clear();
	for(unsigned int i=0; i<cols; i++)
	{
		mat.push_back(std::vector <T> ());
		for(unsigned int j=0; j<rows; j++)
		{
			mat.push_back(x);
			mat[j]=values;
		}
	}
}

template <class T>
unsigned int Matrix<T>::cols()
{
	return mat.size();
}

template <class T>
unsigned int Matrix<T>::rows()
{
	if(mat.size()==0) return 0;
	return mat[0].size();
}

template <class T>
T Matrix<T>::operator () (unsigned int row, unsigned int col)
{
	if (row > rows() || col > cols()) return mat[0][0];
	return mat[col][row];
}

template <class T>
std::ostream & operator << (std::ostream & output, Matrix <T> & mat)
{
	output<<"[\n";
	for(unsigned int i=0; i<mat.cols(); i++)
	{
		for(unsigned int j=0; j<mat.rows(); j++)
		{
			output<<mat(i, j)<<" ";
		}
		output<<"\n";
	}
	output<<"]\n";
	return output;
}

#endif

main.cpp

template <class T>
vector <vector <T> > matrix(unsigned int cols, unsigned int rows, T values)
{
	vector <vector <T> > mat;
	for(unsigned int i=0; i<cols; i++)
	{
		mat.push_back(std::vector <T> ());
		for(unsigned int j=0; j<rows; j++)
		{
			mat.push_back(values);
		}
	}
	return mat;
}

template <class T>
std::ostream & operator << (std::ostream & output, vector <vector <T> > & mat)
{
	output<<"[\n";
	for(unsigned int i=0; i<mat.size(); i++)
	{
		for(unsigned int j=0; j<mat.size(); j++)
		{
			output<<mat[j]<<" ";
		}
		output<<"\n";
	}
	output<<"]\n";
	return output;
}

int main()
{
	unsigned int N=5;
	Matrix <int> theta(N, 2, 50);
	vector <vector <int> > mat=matrix(N, 2, 50);
	cout << theta;
	cout << mat;
	return 0;
}

Output: [ 50 50 50 50 0 0 50 50 50 50 ] [ 50 50 50 50 50 50 50 50 50 50 ] Can anybody tell me why this is happening and how to fix it? Thanks.
Advertisement
template <class T>T Matrix<T>::operator () (unsigned int col, unsigned int row){	if (row > rows() || col > cols()) return mat[0][0];	return mat[col][row];}

or

template <class T>std::ostream & operator << (std::ostream & output, Matrix <T> & mat){	output<<"[\n";	int col = mat.cols();	int rows = mat.rows();	for(unsigned int i=0; i<mat.cols(); i++)	{		for(unsigned int j=0; j<mat.rows(); j++)		{			output<<mat(j, i)<<" ";		}		output<<"\n";	}	output<<"]\n";	return output;}

[grin]
I'm not quite sure how your code even compiles... Unless you didn't paste all of it?
Also most of your loops are sort of useless, you can do something like:
return std::vector<std::vector<T>>( cols, std::vector<T>(rows,values) );
Quote:Original post by Zael
I am trying to implement a matrix class which contains a 2D vector and has methods for matrix operations in the class. At the moment I am having issue with either the initialization or the output function


Without trying to debug it, I will tell you that you can do the initialization much more simply, by taking advantage of the constructors that std::vector provides:

template <class T>Matrix<T>::Matrix(unsigned int cols, unsigned int rows, T values) : mat(cols, vector<T>(rows, values)) {}template <class T>vector<vector<T> > matrix(unsigned int cols, unsigned int rows, T values) {  return vector<vector<T> >(cols, vector<T>(rows, values));}


By the way, it is never useful to .clear() a standard library container in the constructor (unless you put elements into it earlier in the constructor that you have to get rid of; but it's hard to imagine how that would happen). Constructors are called for all data members and bases of a class before the class' own constructor is called. If you don't specify which one (by using the initialization list, as shown above), the default constructor is used. For standard library containers, that initializes the container as an "empty" one with zero initial elements. Similarly, it is never useful to .clear() the standard library container in the destructor (unless... well, it would have to be something even weirder), because the container's destructor will be called afterward, effectively .clear()ing the container anyway.

Oh, and if you really want this kind of multiple-dimensional, rectangular array functionality, don't build it yourself; use boost::multi_array. It's more efficient anyway (because it doesn't have the flexibility in the underlying data to allow each "row" to be a different length, and therefore does not carry the overhead needed to make that possible).
Black Knight called it. I was had my rows before my columns on my () operator, and the rest of my code was using columns first. Thanks Black Knight.

I am aware of the better construction for vectors, but was frustrated because for reasons unknown to me at the time, my code wasn't working. Because my code wasn't working I wanted to break it down so that I was manually inserting each element. Don't ask. It's just the way my brain works.

Thank you Zahlman, I wasn't aware that I could call a constructor to a member class.

This topic is closed to new replies.

Advertisement