| re: copy_constructor doesnt get called ... why ?
Mike <philip-may@gmx.de> wrote in message news:<bermaa$qgl$01$1@news.t-online.com>...
[color=blue]
> The copy_constructor is called when a function returns an
> object (copys it out) right?
> But in this program the operator+ function doesnt call it.
>
> Can someone tell me why please ?[/color]
12.8/15:
"Whenever a temporary class object is copied using a copy constructor,
and this object and the copy have the same cv-unqualified type, an
implementation is permitted to treat the original and the copy as two
different ways of referring to the same object and not perform a copy
at all, even if the class copy constructor or destructor have side
effects."
If a function returns a temporary, and it can be arranged so that the
caller can use it directly, there's no meaningful reason to copy it to
a second temporary, just to destroy both shortly thereafter. C++
simply allows compilers to make the appropriate arrangements.
[color=blue]
> Complex operator+ (const Complex& a, const Complex& b) {
> cout << "operator+\n";
> Complex tempc(a.re + b.re, a.im + b.im);
> return tempc; // <----- !!! THIS SHOULD CALL THE copy_constructor !!!
> }[/color]
Some compilers perform what is called "named return value
optimization" (NRVO) wherein the copy constructor is "elided" (not
called) where unnecessary.
NB: Even more compilers perform unnamed return value optimization
(simply RVO), which is like NRVO except it only works when you return
an unnamed object:
Complex operator+ (const Complex& a, const Complex& b) {
cout << "operator+\n";
return Complex(a.re + b.re, a.im + b.im); // no name; may use RVO
}
For best results, prefer this syntax where applicable.
[color=blue]
> int main(void)
> {
> Complex c1(1.1, 2.2), c2(11.11, 22.22);
>
> c1.Print();
> c2.Print();
>
> cout << "** start c1 = c1 + c2;\n";
> c1 = c1 + c2;[/color]
c1's operator= expects a Complex, and (c1 + c2) returns a Complex, so
the compiler is free to use the returned value directly in the
assignment without extraneous copying.
[color=blue]
> cout << "** end c1 = c1 + c2;\n";
>
> c1.Print();
> c2.Print();
>
> return 0;
> }
> /*
> this is the program output:
>
> constructor
> constructor
> re: 1.1 im: 2.2
> re: 11.11 im: 22.22
> ** start c1 = c1 + c2; <-----+
> operator+ |
> constructor | the copy_constructor should
> operator= | be called somewhere here ...
> destructor |
> ** end c1 = c1 + c2; <-----+
> re: 12.21 im: 24.42
> re: 11.11 im: 22.22
> destructor
> destructor
> */[/color]
g++ 2.95.4 *does* call the copy constructor in that region, but g++
3.2 does not; the latter version performs NRVO. (Note: The former
performs RVO and would not have called the copy constructor if you had
returned an unnamed object.)
- Shane |