Hi,
there is a problem with the example provided. You effectively prevent the compiler from optimizing away all temporaries by making your constructors non-trival(because of the debug output).
The last published draft of the current C++ Standard dictates that a non-trivial constructor of temporaries must be called:
In Section 12.2, Page 259:
When an implementation introduces a temporary object of a class that has a non-trivial constructor (12.1,
12.8), it shall ensure that a constructor is called for the temporary object.
The only exception are non-trivial Copy or Move Constructors, which may be omitted for copy elision:
In Section 12.7, Page 283:
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class
object, even if the copy/move constructor and/or destructor for the object have side effects. In such cases,
the implementation treats the source and target of the omitted copy/move operation as simply two different
ways of referring to the same object, and the destruction of that object occurs at the later of the times
when the two objects would have been destroyed without the optimization.123
This code(essentially the same as above, but without most of the const and without any debug output):
struct Vector2 {
int _x, _y;
Vector2(){};
Vector2(int x, int y): _x(x), _y(y) {}
Vector2(const Vector2 &vec): _x(vec._x), _y(vec._y) {}
Vector2 operator+(const Vector2 &rhs) const {
return Vector2(_x+rhs._x, _y+rhs._y);
}
void add(const Vector2 &src1, const Vector2 &src2) {
_x = src1._x + src2._x;
_y = src1._y + src2._y;
}
};
int main(int argc, char *argv[]) {
Vector2 vec1(1, 1);
Vector2 vec2(2, 2);
Vector2 vec3(3, 3);
Vector2 vec;//=vec1 + vec2 + vec3;
vec.add(vec1,vec2);
vec.add(vec,vec3);
return 0;
}
Produces(on my laptop, g++ version 4.4.5, lowest optimization level) the excact same assembly as the version using the overloaded operator+:
struct Vector2 {
int _x, _y;
Vector2(){};
Vector2(int x, int y): _x(x), _y(y) {}
Vector2(const Vector2 &vec): _x(vec._x), _y(vec._y) {}
Vector2 operator+(const Vector2 &rhs) const {
return Vector2(_x+rhs._x, _y+rhs._y);
}
void add(const Vector2 &src1, const Vector2 &src2) {
_x = src1._x + src2._x;
_y = src1._y + src2._y;
}
};
int main(int argc, char *argv[]) {
Vector2 vec1(1, 1);
Vector2 vec2(2, 2);
Vector2 vec3(3, 3);
Vector2 vec=vec1 + vec2 + vec3;/*
vec.add(vec1,vec2);
vec.add(vec,vec3);*/
return 0;
}
The assembly(generated with a call "g++ -O -S main.cpp") is the following:
Code: Select all
.file "main.cpp"
.text
.globl main
.type main, @function
main:
.LFB11:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
pushl %ebp
.cfi_def_cfa_offset 8
movl %esp, %ebp
.cfi_offset 5, -8
.cfi_def_cfa_register 5
movl $0, %eax
popl %ebp
ret
.cfi_endproc
.LFE11:
.size main, .-main
.ident "GCC: (Debian 4.4.5-8) 4.4.5"
.section .note.GNU-stack,"",@progbits
Of course, having side effects in the Constructor significantly reduce the efficency of a simple addition is still pretty unintuitive and quite undesired behaviour, but instead of falling back to a C like method, one could simply overload operator+=, which would retain a bit of the beauty of the C++ version, whilst being as efficient as the C-like add method in pretty much all cases.
I am sorry if I offended anyone, that is not my intention, I merely wanted to point out the fact that if you know what you are doing overloading operators doesnt necessarily slow down your code(and imho it really does make the code look more beautiful)
Fillius