Why move constructor is not called in my code ? Also why dtor is not called just to destroy temp obj?

Viewed 89

Lines in my code

student g1(student("Larry"));//why move ctor is not called after overloaded ctor???
student g2 = "Delta";//Also here,why move ctor is not called after overloaded ctor???

Also why dtor is not called for unnamed temporary objects created just after????

Actually i am confused totally ,when move ctor is called . On the other hand i have also observed that if i try to push back a temp obj in to a vector expecting obj type elements ,there move ctor is called ,

vector<student> list{};
list.push_back(student("vickey"));

Here, first vickey temp object created then move to the vector by calling move constructor, because student("vickey") is an rvalue. Isn't it?

If above is valid then why here its not valid?

student g1(student("Larry"));
student g2 = "Delta";

Here is my code

#include <iostream>
#include <cstring>
using namespace std;
//===================class declaration============================
class student{
private:
    char *name;
public:
    student();
    student(const char *str);
    ~student();
    student(student &&rhs) noexcept;
    
};
//======================impelmentation=========================
student::student(){
    cout<<"default"<<endl;
    name = new char[5];
    strcpy(name,  "None");
}
student::student(const char *str)
    :name{nullptr}{
        cout << "overloaded" << endl;
        if(str == nullptr){
            name = new char[5];
            strcpy(name, "None");
        }else{
        name = new char[strlen(str) + 1];
        strcpy(name, str);
        }
}

student::student(student &&rhs) noexcept
    :name{rhs.name}{
        cout << "Move ctor" << endl;
        rhs.name = nullptr;
        
}

student::~student(){
    if(name == nullptr)
        cout<<"dtor : nullptr"<< endl;
    else{
        cout<<"dtor : "<<name<< endl;
        delete [] name;
    }
}

//===================================main=====================================
int main() {
    student g1(student("Larry"));
    student g2 = "Delta";
    cout<<"\n=========================================================\n"<<endl;
    return 0;
}

Output:

overloaded
overloaded

=========================================================

dtor : Delta
dtor : Larry
1 Answers

In this line:

 student g1(student("Larry"));

The g1 is constructed using a constructor due to copy elision. In order to move construct g1, you would need to do it explicitly in this case:

student g1(std::move(student("Larry")));

In the case of vec.push_back(student("vickey")); the move constructor is called since std::vector has push_back(T&&) overload and the student("vickey") is an rvalue. This overload resolution leads to invocation of the type's move constructor (implicitly). There's no way to elide copying/moving the object into vector. So, the best we can hope for is the move constructor.

As we already have seen, you can do similarly in your user code, by using std::move.

Note, user code (generally) should not use std::move. It mostly intended for class implementations.

Related