Home > front end >  Why this code is not calling move constructor?
Why this code is not calling move constructor?

Time:05-09

I have this simple piece of code in C 17 and I was expecting that the move constructor was called (or the copy constructor, if I was doing something wrong), while it is just calling the normal constructor and I cannot why is doing this optimization.

I am compiling with -O0 option.

#include <iostream>

using namespace std;

struct Foo {
  int m_x;

  Foo(int x) : m_x(x) { cout << "Ctor" << endl; }

  Foo(const Foo &other) : m_x(other.m_x) { cout << "Copy ctor" << endl; }

  Foo(Foo &&other) : m_x(other.m_x) {
    other.m_x = 0;
    cout << "Move ctor" << endl;
  }
};

void drop(Foo &&foo) {}

int main() { drop(Foo(5)); }

CodePudding user response:

I cannot why is doing this optimization.

This is not due to any optimization in C 17. Instead this is due to the fact that you're passing an int when you wrote Foo(5). And since you've provided a converting constructor Foo::Foo(int), it will be used to create a Foo object which will then be bound to the rvalue reference parameter of drop.

Note that in C 17, even if we were to make the parameter of drop to be of type Foo instead of Foo&&, then also there will be no call to the move constructor because of mandatory copy elison.


C 11

On the other hand, if you were using C 11 and using the flag -fno-elide-constructors and parameter to drop was of type Foo instead of Foo&& then you could see that a call would be made to the move ctor.

//--------vvv-----------> parameter is of type Foo instead of Foo&&
void drop(Foo foo) {
    
    std::cout<<"drop called"<<std::endl;
    
    }

int main() { 
    drop(Foo(5)); //in c  11 with -fno-elide-constructors the move ctor will be called
}

The output of the above modified version in C 11 with -fno-elide-constructors is:

Ctor
Move ctor
drop called

Demo

CodePudding user response:

In function main you create a temporary Foo object from integer 5 but you don't move (nor copy) from it anywhere. To actually call your move (or copy) constructor, you have to move- (or copy-) construct another object from your temporary Foo.

E.g., to call Foo's move constructor:

void drop(Foo &&foo) {
    // Move-construct tmp from foo.
    Foo tmp { std::move(foo) };
}
  • Related