0

First of all, I am not at all an experienced C++ programmer, I am just trying to pass my OOP exam. It is not very clear for me when the copy constructor is called. I knew that there are some "special" cases when giving argument by value to a functions, and when returning by value. Here, where I give arguments by value to void F(A x) everything happens as expected:

#include <iostream>
using namespace std;

class A
{
    int x;
public:
    A(int x = 0)    {
        x = x;
        cout<<"Constructor "<<x<<endl;    }
    ~A(){
        cout<<"Destructor "<<endl;    }

    A(const A&o){
        x = o.x;
        cout<<"Copy constructor"<<endl;
    }
};

A F(){
    A a;
    return a;
}

void F(A x){
}

int main()
{
    //A obj(F());
    A a;
    F(a);
}
///

The output is:

Constructor 0
Copy constructor
Destructor
Destructor

Because the Constructor 0 is showed when declaring A a, the copy constructor and the destructor are showed because of the function call, cause the parameter is passed by value, and the final destructor is the destructor for a.

It is not very clear for me why in the next case the behaviour is so different:

#include <iostream>
using namespace std;

class A
{
    int x;
public:
    A(int x = 0)    {
        x = x;
        cout<<"Constructor "<<x<<endl;    }
    ~A(){
        cout<<"Destructor "<<endl;    }

    A(const A&o){
        x = o.x;
        cout<<"Copy constructor"<<endl;
    }
};

A F(){
    A a;
    return a;
}

void F(A x){
}

int main()
{
   A obj(F());

}
///

Now, the output is:

Constructor 0
Destructor

It seems like only the A a inside the A F() is called. Why isn't the copy constructor called when calling F()? Doesn't it return by value, isn't the copy constructor called ? Moreover, when declaring A obj(F()) why isn't the copy constructor called at leas for obj ?

  • *It is not very clear for me why in the next case the behaviour is so different:* -- Before C++ 11, asking "how many times is the copy constructor called?" was a trick question. It may still be a trick question. You could take the same compiler, and depending on the compiler options used, you would get a different answer / output. So the answer to "how many times is the copy constructor called?" -- It depends. BTW, I like your last name :) – PaulMcKenzie Jun 10 '21 at 14:49

1 Answers1

2

That's because the compiler will "optimize" (it's actually told by the standard now to do so) the copy away and instead directly construct your A in the place where the function would return it to.

That's called copy elision (well actually NRVO, "named return value optimization", in your case as explained in that link)

Stefan Riedel
  • 796
  • 4
  • 15
  • so my compiler "cheats" ? If it respected the rules, those copy constructors would have been called like I said, am I right ? –  Jun 10 '21 at 14:40
  • No, I edited the answer. Since c++17 your compiler has to omit a copy/move, before that, it was just an optimization it was allowed to do. – Stefan Riedel Jun 10 '21 at 14:42
  • @alexMcKenzie No. As mentioned in the answer - the compiler is required to elide the copy, by the newest C++ standards. – Algirdas Preidžius Jun 10 '21 at 14:43
  • @alexMcKenzie Your compiler is following _the rules_ of the standard. By "cheats", might you be saying that it doesn't do what you expect? – Drew Dormann Jun 10 '21 at 14:43
  • @DrewDormann At school they didn't tell us about copy elision, they told us that when passing and returning by value the copy constructor is called. But I think I got it now, thank you. –  Jun 10 '21 at 14:51
  • @alexMcKenzie -- You should still write the code as-if the copy constructor will be called. The copy elision is not fully under your control. Maybe that's what the teacher was trying to point out. – PaulMcKenzie Jun 10 '21 at 14:55