I have a problem understanding the concept of vectors working with move semantics and objects. I'll put the code and explain you the problem exactly, because I really want to understand the logic behind this.
#include <iostream>
#include <vector>
#include <cstring>
#include "Mystring.h"
using namespace std;
class Mystring {
private:
char* str;
public:
Mystring();
Mystring(const char* s);
Mystring(const Mystring& source);
Mystring(Mystring&& source);
~Mystring();
Mystring& operator=(const Mystring& rhs);
Mystring& operator=(Mystring&& rhs);
void display() const;
int get_lenght() const;
const char* get_str() const;
};
int main() {
vector <Mystring> stooges_vec;
stooges_vec.push_back("Larry"); //11
stooges_vec.push_back("Moe"); //12
stooges_vec.push_back("Curly"); //13
return 0;
}
//One-args constructor
Mystring::Mystring(const char* s)
: str{ nullptr } {
if (s == nullptr) {
str = new char[1];
*str = '\0';
}
else {
str = new char[std::strlen(s) + 1];
std::strcpy(str, s);
}
}
//Copy constructor
Mystring::Mystring(const Mystring& source)
:str{ nullptr } {
str = new char[std::strlen(source.str) + 1];
std::strcpy(str, source.str);
}
//Move constructor
Mystring::Mystring(Mystring&& source)
:str{ source.str } {
source.str = nullptr;
std::cout << "Move constructor called." << std::endl;
}
//Destructor
Mystring::~Mystring() {
delete[] str;
}
//Copy assignment
Mystring& Mystring::operator=(const Mystring& rhs) {
std::cout << "Copy assignment called." << std::endl;
if (this == &rhs)
return *this;
delete[] str;
str = new char[std::strlen(rhs.str) + 1];
std::strcpy(str, rhs.str);
return *this;
}
//Move assignment
Mystring& Mystring::operator=(Mystring&& rhs) {
std::cout << "Move assignment called." << std::endl;
if (this == &rhs)
return *this;
delete[] str;
str = rhs.str;
rhs.str = nullptr;
return *this;
}
So, the problem is that I don't understand the process of this program. I took the debugger and everything is fine:
For the first object that I want to add, the "one args constructor" is called first so I create my object, then "the move constructor" gets called so I steal the data and null the pointer of the original object. I finish it, push my object into the vector and I destroy the original object that now sits with a null pointer in it.
Here I get lost for good, because the process looks the same except after that line
std::cout << "Move constructor called." << std::endl;
the control goes to the copy constructor and I notice (I hope I'm not wrong) that he does a copy ofLarry
.
The problem is: I have no clue why the compiler wants to make a copy of Larry
. It's there, so the compiler can't simply create Moe
, use the move semantics and just push Moe
at the back of the vector? Why does it have to make a copy?
Plus, a very strange behavior for me is that I see a destructor called after that copy constructor of Larry
because I see it being destroyed. I mean, what is the compiler destroying at this point? The original Larry
so it keeps the copy, or what's exactly happening there?
Can someone explain to me what is exactly happening in that second push_back()
?