Will my compiler automatically reuse the return value of this method?

I'm wondering if my compiler will be smart enough to realize that the determinant() of this matrix has already been calculated and will reuse the value that was calculated earlier, or if I need to explicitly handle this to optimize the code to avoid calling determinant() twice? (ie, determinant() is being redundantly called inside of inverse(). m is not being changed between the two calls.)

My matrix code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Matrix2 {
    std::array<real_t, 4> data;
public:

...

    real_t determinant() const {
        return data[0] * data[3] - data[1] * data[2];
    }

    Matrix2 inverse() const {
        real_t det_inv = 1.0 / determinant();
        return Matrix2(data[3] * det_inv, -data[1] * det_inv, -data[2] * det_inv, data[0] * det_inv);
    }
};


Using the matrix later on:

1
2
3
4
5
6
7
Matrix2 m = calc_matrix();
if (abs(m.determinant()) < 1e-6) {
	//Special handling
	return;
}

Matrix2 m_inv = m.inverse();
Last edited on
Hi

Have you considered having a member of the class that the value of determinant() is assigned to? You should make it private and mutable.

Edit: To answer your question: No the compiler will not automatically reuse that value, it is a temporary.

If the determinant is calculated once, call that function in a constructor. Otherwise call as required.
Last edited on
I agree the answer is no, the compiler is not smart enough in general, but for small programs where everything is visible to the compiler all at once, it will sometimes collapse logic down if you have aggressive optimizations on (like -O3).

There's the Compiler Explorer you can use to test out theories about how the compiler will optimize piece of code: https://godbolt.org/

But I also disagree with TheIdeasMan; I seldom see it as a good idea to use mutable. Mostly because it forces you to toss out any semblance of thread safety and the compiler now cannot assume the state of the object is truly constant. I'm not saying to never use it, but I've seen it used as a way to preserve a backwards compatible interface with other components that expect a const object, while implementing caching (but those other components still have to know that things like thread safety are now out the window).
Last edited on
Registered users can post here. Sign in or register to post.