Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to bypass "returning reference to local variable" problem?

Tags:

c++

I have a homework exercise. I'm almost sure it's unsolvable the way they ask it. However, I'm interested if you guys have any solution for the problem mentioned below because it seems like something that often occurs.

The description is not long, so I share it with you below:

A matrix S ∈ R n×n is skewsymmetric if it holds that S(Transpose) = −S. Derive from the class SquareMatrix from the lecture the class SkewSymmetricMatrix. Use a vector of length n(n − 1)/2 to store the matrix entries. Implement constructors, type casting and a suitable access to the coefficients.

The problem occurs while trying to provide the access, because the virtual access method defined in SquareMatrix returns a reference.

const double& SquareMatrix::operator()( int j, int k ) const
{
    assert( j >= 0 && j < m );
    assert( k >= 0 && k < n );
    return coeff[ j + k * m ];
}

However, I can't return reference to the not stored variables. The following code is just for demonstrating my problem. In this case the j > k block would obviously not work.

const double& SkewSymmetricMatrix::operator()( int j, int k ) const
{
    assert( j >= 0 && j < size() );
    assert( k >= 0 && k < size() );
    if( j < k )
    {
        const double* coeff = getCoeff();
        return coeff[ j * ( j - 1 ) / 2 + k ];
    }
    else if ( j > k )
    {
        const double* coeff = getCoeff();
        return -coeff[ k * ( k - 1 ) / 2 + j ];
    }
    else
    {
        return const_zero;
    }
}

Do you have any suggestions that how to provide a proper access operator while trying to reduce the use of memory by

  1. storing less elements
  2. and calculating the non-stored desired elements from the actually stored ones?
like image 213
MBT Avatar asked Nov 17 '22 06:11

MBT


1 Answers

One idea in comments was using a temporary private member and return a reference to it. That would be a really bad idea:

If you use a reference to a private member, the value changes at next call. If the caller uses:

const double& val1 = my_square_matrix(2, 1);
const double& val2 = my_square_matrix(3, 1);
double sum = val1 + val2;

The result will be val2 + val2, not val1 + val2, because the wrong value is referenced.

But there are two solutions to fulfill the requirements:

  1. Implement a get-method and throw an exception, if the parentheses-operator is called.

  2. Make a second member vector, but leave it empty. Always if you access a not existent element, check the vector (and resize it once to n(n-1)/2 if empty, but never to another size!), and write the value at the desired position. Then, return a reference to this position. Only once resize the vector, because it can allocate new memory if resized, so old references would get invalid.

like image 100
Anton F. Avatar answered Jan 09 '23 13:01

Anton F.