Please help me understand whats happening in following 3 cases.
In the provided code
#include <iostream>
using namespace std;
class Dummy {
public:
string content;
Dummy(string c) : content(c) { cout << "Constructor" << endl; }
Dummy(const Dummy &o) : content(o.content) {
cout << "Copy Constructor" << endl;
}
// Dummy(const Dummy &o) = delete;
Dummy(Dummy &&o) noexcept {
content = std::move(o.content);
cout << "Move Constructor" << endl;
}
Dummy &operator=(const Dummy &o) {
cout << "Assignment" << endl;
content = o.content;
return *this;
}
Dummy &operator=(Dummy &&o) {
cout << "Move Assignment" << endl;
content = std::move(o.content);
return *this;
}
~Dummy() { cout << "Destructor" << endl; }
};
Dummy returnDummyObject(string c) {
Dummy d{c};
return d;
}
void takeDummyParam(Dummy d) { cout << d.content << endl; }
int main() {
cout << "Case 1" << endl;
Dummy d1 = returnDummyObject("some string 1");
cout << "Case 2" << endl;
Dummy d2 = std::move(returnDummyObject("some string 2"));
cout << "Case 3" << endl;
Dummy d3 = Dummy{"some string 3"};
cout << "Case 4" << endl;
Dummy d4 = d3;
}
Output is:
Case 1
Constructor
Case 2
Constructor
Move Constructor
Destructor
Case 3
Constructor
Case 4
Copy Constructor
Destructor
Destructor
Destructor
Destructor
What exactly is happening in Case 1? I created a dummy object inside that function and then created another dummy object using that. It should have used a constructor and then a copy constructor (or move constructor based on whether it returns lvalue or rvalue).
Why does Case 2 work? Shouldn't object returned by a function be an rvalue? I am confused because std::move turns lvalue to rvalue.
In Case 3 it just uses a constructor. My assumption was that it will use constructor and then a copy constructor. Can I use construct like this everywhere without it doing any unnecessary copy?
Type t = Type{args}
Thanks in advance. I just started learning c++ using c++ primer 5th edition. Confused about above cases.