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
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) };
}
