0

In the below example I want to find out why the copy constructor isn't called when I return an automatic variable from the doit() function. I understand that the first version of handler is called because we have a temporary object but can't figure out why the copy constructor isn't called while creating that temporary object (copies everything from s to a temporary object).

#include <iostream>
using namespace std;


class S{
    public:
        S(){std::cout<<"Constructor\n";}
        S(const S& s){std::cout<<"Copy Constructor\n";}
        ~S(){std::cout<<"Destructor\n";}
};

S doit(){
    S s;
    return s; 
}

void handler(S&& r){
    std::cout<<"Here\n";
}
void handler(const S& r){
    std::cout<<"Here2\n";
}

int main() {
    handler(doit());
}

  • https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization – rafix07 Nov 04 '20 at 12:34

1 Answers1

1

Actually, there is a constructor being called in your code according to the rules of the language. However, the compiler has optimized that out and so you don't see the call. If you compile with -fno-elide-constructors you should see the copy-constructor being invoked.

Note that the copy-constructor will only be invoked because the defaulted move-constructor is suppressed. If you add that back like this:

S(S&&) = default;

then this move-constructor will be called instead. Here's a demo.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • Thought so but wasn't sure, as I compiled it in an online compiler – Erik Nouroyan Nov 04 '20 at 12:36
  • @ErikNouroyan Using an online compiler shouldn't make any difference really. – cigien Nov 04 '20 at 12:38
  • Actually it does, adding `S(S&&) = default;` this doesn't make the copy constructor be called – Erik Nouroyan Nov 04 '20 at 12:39
  • @ErikNouroyan Yes, but because the move-constructor is called. (it has nothing to do with an online compiler). See the demo link, where I `cout` in that constructor instead of defaulting it so you can see the call clearly. – cigien Nov 04 '20 at 12:40
  • Ah now I got it thank you,if I do `S(S&&) = delete;` I hope it should call the copy constructor – Erik Nouroyan Nov 04 '20 at 12:41
  • @ErikNouroyan Yes, it will. Note that you don't even have to `=delete` the move-constructor, since it doesn't get generated in this case anyway. – cigien Nov 04 '20 at 12:43
  • Actually it didn't work, moreover when I add cout to this `S(S&&)` it doesn't show the message, it depends on the compiler I guess – Erik Nouroyan Nov 04 '20 at 12:44
  • @ErikNouroyan No, it depends on the flag that I mentioned in the answer. Without that flag being passed explicitly, by default compilers have been optimizing out calls like that for at least 20 years. – cigien Nov 04 '20 at 12:45
  • @ErikNouroyan No problem :) Consider accepting the answer if it does actually answer your question. – cigien Nov 04 '20 at 12:57