c++move-constructor

Why is the move constructor is not being called?


Below is my C++ code. I was expecting my move ctor to be called here in my main:

Mystring larry2 = "some larry";

main.cpp:

int main()
{
    //Mystring no_name;
    Mystring larry ("LARRY");
    Mystring larry1 {larry}; // deep copy ctor is called
    Mystring larry2 = "some larry"; // move ctor should be called but still calling parameterized ctor
}

Mystring.cpp:

Mystring::Mystring()
    :str{nullptr} {
    cout <<"default ctor called" <<endl;
    str = new char[1];
    *str = '\0';
}

Mystring::Mystring(const char *s)
    :str{nullptr} {
    cout << "param ctor called" << endl;
    if(s == nullptr) {
        // then do same as default ctor;
        str = new char[1];
        *str = '\0';
    }else {
        str = new char[std::strlen(s) + 1];
        std::strcpy(str, s);
    }
}

Mystring::~Mystring() {
    cout << "dtor called: " << this->str << endl;
    delete []str;
}

//deep copy ctor implementation
Mystring::Mystring(const Mystring &source)
    :str{nullptr} {
    cout << "deep copy ctor called" <<endl;
    str = new char[std::strlen(source.str) + 1];
    std::strcpy(str, source.str);
}

//move ctor implementation
Mystring::Mystring(Mystring &&source) noexcept
    :str(source.str) {
    cout << "move ctor called" << endl;
    source.str = nullptr;
}
 
void Mystring::display() const {
    cout << this->str << endl;
}

Mystring.h:

class Mystring {
private:
    char *str;
public:
    Mystring(); // default ctor
    Mystring(const char *source); //parameter ctor
    ~Mystring();
    Mystring(const Mystring &source); //copy ctor
    Mystring(Mystring &&source) noexcept; //move ctor
 
    void display() const;
};

I tried multiple sources.


Solution

  • I assume you expected a move ctor in this line:

    Mystring larry2 = "some larry"; 
    

    because you thought a temporary object is first constructer from "some larry", and then it is moved into larry2.

    But in fact this line is not performing an assignment, but rather an intialization of larry2.

    It is equivalent to:

    Mystring larry2{"some larry"}; // or: larry2("some larry");
    

    And therefore invokes a single call of the constructor that accepts a const char*.

    A side note:
    It's better to avoid using namespace std; - see here.