confused about move constructor definition in derived class

Hello everyone, I am confused about how to define move constructor in derived class. I do not know if it is correct to realize it as below. Since after std::move(x), x should not be used to access its members before assignment again.
But I used it in the derived class. If not, I can't find other ways to do it.
Could someone explain to me the correct way to define it?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Base
{
public:
    Base() = default;
    Base(const std::string &s): bookNo(s) {}
    Base(const Base &) = default;
    Base(Base &&b): bookNo(std::move(b.bookNo)) {}
    ~Base() = default;
private:
    std::string bookNo;
};
class Derived : public Base
{
public:
    // ...
    Derived(Derived &&d): Base(std::move(d)), revenue(std::move(d.revenue)) {}      
// ???? d should not be used after std::move(d) to access revenue here in my opinion 
private:
    string revenue;
};
Last edited on
Base does not know that revenue exists. Therefore, its move will not touch the revenue.
As revenue is type double and doesn't use dynamic memory, there's no point using move with revenue. move semantics are only for objects that use dynamic memory where memory pointers are swapped/copied etc and not the referenced memory.
@maple,
A word of advice: Use code tags and indenting to make your code easier to read.
PLEASE USE CODE TAGS (the <> formatting button to the right of this box), when posting code.

Along with the proper indenting, it makes it easier to read your code, and thus also easier to respond to your post.

Tutorials on how to use code tags:

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

I found the second link to be the most help.

Tip: You can hit "edit post", highlight your code and then press the <> formatting button. This will not automatically indent your code. That part is up to you.

You can use the "preview" button at the bottom to see how it looks.


Best,
max
Last edited on
First, thanks for your advice, @agent max.
I am sorry to use std::move() on double type (which is a bad example), and I changed it into string type. @seeplus.
But it is not my point. My question is that after std::move(x) used, x can not access its members. Like in this code, Base(std::move(d)), the move operation is done first, even if the parameter Base accepts is Base type, but for d(Derived type), it is already moved. It should not access its members. Did I make any misunderstanding here about std::move() ?
The std::move does not modify object. It is just a hint for overload resolution to choose the move ctor/assingment over copy ctor/assignment.
See https://en.cppreference.com/w/cpp/utility/move

It is the move constructor that modifies the object. Lets look at it:
1
2
3
Base::Base( Base &&b )
 : bookNo( std::move(b.bookNo) )
{}

The only thing in b that is modified is the b.bookNo.
Therefore,
1
2
3
4
Derived::Derived( Derived &&d )
 : Base( std::move(d) ), // modifies d.bookNo
   revenue( std::move(d.revenue) ) // modifies d.revenue
{}
Last edited on
move leaves the object in an unspecified but valid state. Hence it's perfectly legal to reuse the object or access one of the members.
@keskiverto, I think I understand a little now.

1
2
3
Base::Base( Base &&b )
 : bookNo( std::move(b.bookNo) )
{}


You mean b.bookNo here is modified is because it called string::string(string &&), which modified the value of b.bookNo, right ?

According to your explanation, even if we used std::move(x); we can still use x to access its members and the members should have the same information like below:

1
2
3
4
5
6
Derived d("0-2-9999", "1-1-1111");
Base b(std::move(d));
cout << d.revenue << endl;

// here can we still get the output "1-1-1111" ??? guess yes, but not sure.
// while for d.bookNo, generally it may be null string depending on string::string(string &&). 


Did I understand correctly this time ? Thank you for checking again.
Yes.
Thanks a lot @keskiverto.
Topic archived. No new replies allowed.