I'm trying to understand move semantics, and wrote some simple code to exemplify different types of methods according to the C++ rule of five, but I'm encountering a practical issue regarding the move constructor of a custom class myClass
:
#include <vector>
#include <iostream>
class myClass{
std::vector<float> data;
public:
//ctors
myClass() : data (std::vector<float> (1,0.0)) {
printf("empty ctor\n");
};
myClass(const myClass& _other) {
printf("copy ctor\n");
data=_other.data;
};
myClass(myClass&& _other) {
printf("move ctor\n");
if (this != &_other) {
data=_other.data;
_other.data.clear();
}
};
//dtor
~myClass() { data.clear(); };
//op overloads
myClass& operator=(const myClass& _other) {
printf("copy assignment\n");
data=_other.data;
return *this;
};
myClass& operator=(myClass&& _other) {
printf("move assignment\n");
if (this != &_other) {
data=_other.data;
_other.data.clear();
}
return *this;
};
//gp members
void push_val(float _val) { data.push_back(_val); };
float get_val(int _ind) { return data[_ind]; };
};
myClass myFunc() {
myClass FF;
return FF;
};
int main(int argc, char const *argv[]){
// empty ctor:
myClass A;
// copy ctor:
A.push_val(1.0);
myClass B = A;
// move ctor:
myClass C = myFunc();
myClass D = std::move(myFunc());
// copy assignment:
A = C;
// move assignment:
B = myFunc();
return 0;
}
which provides the output:
empty ctor
copy ctor
empty ctor
empty ctor
move ctor
copy assignment
empty ctor
move assignment
which is mostly what was expected, with the exception of one particular case: when instantiating C
, which assigns the output of myFunc()
(which I was assuming to be an rvalue), the empty constructor of myClass
is called instead of the move constructor. Weirdly, when testing the move assignment operator with B = myFunc()
, the out put is as expected. What exactly am I missing here?