Optimalization

One of the typical usage of the references is returning from function by reference rather than by value. Returning reference often more effective than copying. In some cases, however, copying is a must.


template <typename T>
class matrix
{
public:
    // ...
          T& operator()(int i, int j)       { return v[i*cols+j]; }
    const T& operator()(int i, int j) const { return v[i*cols+j]; }

    matrix& operator+=( const matrix& other)
    {
        for (int i = 0; i < cols*rows; ++i)
            v[i] += other.v[i];
    }
private:
    // ...
    T* v;
};

template <typename T>
matrix<T> operator+( const matrix<T>& left, const matrix<T>& right)
{
    matrix<T> result(left);
    result += right;

    return result;
}

Let us discover the return values one-by-one:


    T& operator()(int i, int j)  { return v[i*cols+j]; }

This function returns reference to the selected value, allowing clients to modify the appropriate element of the matrix:


    matrix<double> dm(10,20);
    // ...
    dm(2,3) = 3.14;  // modify metrix element
    cout << dm(2,3); // copies matrix element
    dm(2,3) += 1.1;  // modify matrix element

    double& dr = dm(2,3);   // doesn't copies
    dr += 1.1;              // modify matrix element

A second version of operator() is presented to read constant matrices.


  const T& operator()(int i, int j) const { return v[i*cols+j]; }

This const memberfunction must return const reference, otherwise the const-correctness would be leaking:


    const matrix<double> cm = dm;
    // ...
    cm(2,3) = 3.14;  // syntax error: returns with const reference
    cout << cm(2,3); // ok: copies (read) matrix element
    cm(2,3) += 1.1;  // syntax error: returns with const reference

    double& dr = cm(2,3);   // syntax error: const reference
                            // does not convert to reference
    const double& cdr = cm(2,3);    // ok, doesn't copy  

Most assignment operators defined with (non-const) reference type as return value:


    matrix& operator=(const matrix& other);

    matrix& operator+=( const matrix& other)
    {
        for (int i = 0; i < cols*rows; ++i)
            v[i] += other.v[i];
    }

This is more effective than a value returning type, and also avoiding unneccessary restrictions:


    dm1 = dm2 = dm3;

    ++( dm1 += dm2 );


In the previous examples returning reference (or constant reference) was safe, because the memory area which was referred survived the operation. In the next addiotion returning a reference (or constant reference) would be a major fault:


template <typename T>
matrix<T> operator+( const matrix<T>& left, const matrix<T>& right)
{
    matrix<T> result(left);     // local variable: automatic storage
    result += rigth;

    return result;      // result will disappear: must copy
}