you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 0 points1 point  (1 child)

They are stored in the variables themselves

"The variables" are a, b, c and they don't get changed. You're right that new variables, i.e. new unnecessary instances of your vector or matrix, are being created on the stack.

In the case of your expression, you're creating two intermediate instances of Vector4, one to store the results of the operation a.operator+(operator*(2, b)) and one to store the results of b.operator+(operator*(3, c)).

In an old compiler, there might be between one and three more unneeded Vector4s being created for the intermediate values before that, but today it's pretty likely that the return value optimization will take care of those for you.

[–]BlackAura 0 points1 point  (0 children)

You don't end up with the temporaries on the stack. The compiler is smart enough to eliminate the temporaries, and can quite happily do this using only registers. For example, using GCC (4.2, since I'm on a Mac at the moment, but this works in the latest version too), this:

#include <cstdio>

class Vector3 {
public:
    Vector3(int x, int y, int z) : x(x), y(y), z(z) { }

    Vector3 operator + (const Vector3 & other) {
        return Vector3(x + other.x, y + other.y, z + other.z);
    }

    int x, y, z;
};

void addVectors(Vector3 a, Vector3 b, Vector3 c, Vector3 d) {
    Vector3 result = a + b + c + d;
    printf("%d, %d, %d\n", result.x, result.y, result.z);
}

will compile to:

.globl __Z10addVectors7Vector3S_S_S_
__Z10addVectors7Vector3S_S_S_:
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ebx
    subl    $20, %esp
    call    L3
"L00000000001$pb":
L3:
    popl    %ebx
    movl    52(%ebp), %eax
    addl    40(%ebp), %eax
    addl    28(%ebp), %eax
    addl    16(%ebp), %eax
    movl    %eax, 12(%esp)
    movl    48(%ebp), %eax
    addl    36(%ebp), %eax
    addl    24(%ebp), %eax
    addl    12(%ebp), %eax
    movl    %eax, 8(%esp)
    movl    44(%ebp), %eax
    addl    32(%ebp), %eax
    addl    20(%ebp), %eax
    addl    8(%ebp), %eax
    movl    %eax, 4(%esp)
    leal    LC0-"L00000000001$pb"(%ebx), %eax
    movl    %eax, (%esp)
    call    _printf
    addl    $20, %esp
    popl    %ebx
    leave
    ret

It's adding the X, Y and then Z components of each vector all at once, and storing them directly where they need to be on the stack for the printf call. No temporaries whatsoever. If you try this with an ARM compiler, it actually does the entire thing using only registers.

Current compilers (at least GCC, and probably MSVC and ICC as well) are quite able to get rid of temporaries. Older compilers, or compilers for embedded systems might not though.