3

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
rawrex
  • 4,044
  • 2
  • 8
  • 24
  • Those are constructors; they don't need to move. `student g0 = "Alpha"; student g3 = std::move(g0);` would do a move. – Eljay Jun 19 '21 at 13:09
  • The compiler may optimize a lot of things for you. Like to construct an object directly instead of invoking a copy/move constructor. Yet, even if the compiler omits the call to either of these, they should still be accessible when used. – rawrex Jun 19 '21 at 13:11
  • @Eljay can u please explain me in detail when move ctor will be called , and why here not?? – Saurabh Raj Jun 19 '21 at 13:12
  • A move ctor will be called when an existing object is being move constructed into a newly constructed object. It may also be moved when a temporary object is used to move construct into a newly constructed object (but that likely may be optimized by the compiler). Because of the rules of the language, side-effects (like printing something in the constructor) cannot be relied upon since constructors can be elided. Lesson is: constructors should construct objects into a coherent state. – Eljay Jun 19 '21 at 13:17

1 Answers1

2

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.

rawrex
  • 4,044
  • 2
  • 8
  • 24
  • Moving a temporary is pointless. Even a code smell, indicative of cargo cult programming. The library sees nothing a user defined type doesn't in this case. Move-semantics are ingrained in the core language. – StoryTeller - Unslander Monica Jun 19 '21 at 13:24
  • And your edit contradicts your own answer. You say a `std::move` is needed here, and then say it's ill-advised!? – StoryTeller - Unslander Monica Jun 19 '21 at 13:26
  • @StoryTeller-UnslanderMonica I did not said `std::move` is **needed**. I said that the OP **would need** it, for whatever reason the OP needs to do it. – rawrex Jun 19 '21 at 13:28
  • @rawrex as u have said that The g1 is copy constructed from a temporary object. How it is copy constructed? even we know that student("Larry") is an r-value,then the expression should be equivalent to student g1(r-value); that should invoke move ctor,I think. – Saurabh Raj Jun 19 '21 at 17:26
  • @SaurabhRaj corrected the answer. Check the edit. – rawrex Jun 20 '21 at 15:40
  • @StoryTeller-UnslanderMonica hey, friend! I want to thank you for your input! I got to admit, I did messed that one up. – rawrex Jun 23 '21 at 04:42