Hi Guys, I am trying to teach myself templates in C++.
My current assignment is to create a matrix class by using vector of vectors. I have got most of it done but my code is crashing when I try to overload the random access operator in my matrix class. Here are the relevant code snippets

// This is the array class and I think this works fine
    template<class V, class I =int>
    class Array{

        private:
            vector<V> myStore;

        public:
            Array();
            Array(int size);
            Array(int size, V value);
            ~Array();

            int size();
            const V& element(I index);
            V& operator[] (I index);
    };

// This is the function definition for the Array random access operator    


    template<class V, class I> V& Array<V,I>::operator [](I index){
        return this->myStore[index];
    }



// This is the matrix class 


    template<class V, class I = int>
    class Matrix{

        private:
            vector<Array<V,I> >myStore;

        public:
            Matrix();
            Matrix(int rows, int columns);
            Matrix(int rows, int columns, V value);
            ~Matrix();

            int rows();
            int columns();

            V& operator() (int row, int column);
    };

// This is the function definition for the Matrix random access operator. 


    template<class V, class I> V& Matrix<V,I>::operator ()(int row, int column){
        Array<V,I> myArray = this->myStore[row];    
        return myArray[column];
    }

My code does not crash when I return by value from the above function. What am I doing wrong. Any help is much appreciated

Recommended Answers

All 3 Replies

You're returning a reference to a local variable. The local variable gets destroyed, so the reference is dangling. Just return a reference to myStore[row] directly:

template<class V, class I> 
V& Matrix<V,I>::operator()(int row, int column)
{   
    return myStore[row][column];
}

Alternatively you can make a local reference to the row, then return a reference to the column:

template<class V, class I> 
V& Matrix<V,I>::operator()(int row, int column)
{
    Array<V,I>& myArray = myStore[row];    
    return myArray[column];
}

On a side note, you should consider overloading the operator for const objects as well, and return a const reference:

template<class V, class I> 
const V& Matrix<V,I>::operator()(int row, int column) const;

@decepticon thanks so much for the answer. One more question can you elaborate on the need for returning a const reference?

One more question can you elaborate on the need for returning a const reference?

A const reference would be returned when you want a read-only element, but don't know if the type represented by V is cheap to copy or not. Returning a non-const reference is nonsensical if the matrix itself is const (ie. const Matrix<int, 10> cmat;), so when you write a const operator, it should return a const reference as well. You'd have two versions, one const and one non-const to account for these cases:

// For non-const objects, allows modification of the reference
V& operator()(int row, int column);

// For const objects, disallows modification of the reference
const V& operator()(int row, int column) const;
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.