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