Derived class move constructor

Hi, I got a bit confused about looking at this example in Scott Meyers book "Effective Modern C++". Here is the example

1
2
3
4
5
6
class SpecialPerson: public Person{
public:
        SpecialPerson(SpecialPerson&& rhs)
        : Person(std::move(rhs))
        {...}
};


I read that I'm only supposed to move the object when I'm done using it but here I move it to base class move constructor and than I have to use it again to initialize SpecialPerson specific parts.

I made a small example and it still actually worked. Base class is containing name and derived class is containing surname. I obviously trying to move both parts from one SpecialPerson to another. If you run the the code you can see that it works

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <string>
#include <utility>


class Person{
    std::string name;
protected:
    std::string get_name() const { return name; }
public:
    Person(const std::string& p) : name{p}{}
    
    Person(const Person& p) : name{p.name}{}
    Person(Person&& p) : name{std::move(p.name)}{}
    
    friend std::ostream& operator<<(std::ostream& os, const Person& p);
};


class SpecialPerson : public Person{
    std::string surname;
public:
    SpecialPerson(const std::string& n, const std::string& s) : Person{n}, surname{s}{}
    
    SpecialPerson(const SpecialPerson& sp) : Person{sp}, surname{sp.surname}{}
    SpecialPerson(SpecialPerson&& sp) : Person{std::move(sp)}, surname{std::move(sp.surname)}{}
    
    friend std::ostream& operator<<(std::ostream& os, const SpecialPerson& p);
};


std::ostream& operator<<(std::ostream& os, const Person& p)
{
    return os << p.name;  
}

std::ostream& operator<<(std::ostream& os, const SpecialPerson& p)
{
    return os << p.get_name() << " " << p.surname;
}


int main()
{
    SpecialPerson p{"John", "Neeman"};
    SpecialPerson p2{std::move(p)};
    
    std::cout << p << std::endl;   // ... empty line
    std::cout << p2 << std::endl;  // John Neeman
}


Can anyone explain why I still can access what I need from this rvalue reference even when it was moved to initialize base class?
Last edited on
1
2
3
4
5
6
class SpecialPerson: public Person{
public:
        SpecialPerson(SpecialPerson&& rhs)
        : Person(std::move(rhs))               // < -- moves the Person portion of the object.
        {...}
};


The Person move constructor takes an rvalue-reference to a Person object. It does not modify any portion of the object specific to the SpecialPerson type. As long as you don't access the parts of rhs specific to a Person type after it's been fed to the Person constructor, everything is all good.
The idea of the move constructor is that you are permitted (but not obliged) to leave the source object in an unusable state.

If you copy an object, there is an expectation that the source object doesn't change . You could, of course, write a copy constructor that trashes the source object; you'd be very unpopular, because everyone expects that a copy constructor doesn't change the source object.

With a move operator, everyone knows that the source object is allowed to be left in an unusable state, and will expect that if leaving it in an unusable state makes the move faster, it will be.

That's all it means. It's a way of communicating to the programmer; use copy if the source should still be usable afterwards, use move if you're never going to use the source object again and you don't care if it's left in an unusable state.

Can anyone explain why I still can access what I need from this rvalue reference even when it was moved to initialize base class?

Sorry, what is it that you're accessing that you need to? Which line of code is doing something you don't expect?
Last edited on
Tnx you guys very much, putting this all together makes perfect sense :)
I was talking about line 26 - why I'm able to still use sp when it was already moved to base class constructor :)
Last edited on
Topic archived. No new replies allowed.