0

I'm trying to understand the following

#include <iostream>

class Number {
  int _value;
public:
  Number(int number) : _value(number) { std::cout<<"constructed!\n"; }
  Number(const Number& other) : _value(other._value) { std::cout<<"copied!\n"; }
  ~Number() { std::cout<<"destructed!\n"; }
};

Number create_number(int value) {
  Number out(value);
  return out;
}

int main() {
  Number my_number = create_number(10);
}

The output is

constructed!
destructed!

I would have expected that inside create_number an object would be constructed, copied to the output of the function and then destructed once the function returned.

Something like that seems to happen because if I make the copy constructor explicit

explicit Number(const Number& other) : _value(other._value) { std::cout<<"copied!\n"; }

the compiler yells on return out with no matching constructor for initialization of 'Number'. If I call the copy constructor within create_number explicitly or even cast the Number out to a Number (huh?)

return Number(out);
return (Number)out;

the compiler is happy and I get the expected output

constructed!
copied!
destructed!
destructed!

I feel like I'm missing something about return, copy constructors and/or (implicit) casting. Can someone explain this?

Michael
  • 878
  • 5
  • 17

1 Answers1

2

That's copy elision. Without getting too much into the C++ standard's obscure language, in most cases the compiler may elide (optimize away) the copy, but isn't required to. This is treated like any other optimization.

Interestingly, this is a rare exception to the as-if rule, where the side-effects of an optimization are observable - see the notes in these links.