move constructor and assignment

I have took the program from the article :
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
#include <iostream>
#include <string>
using namespace std;

class Example6 {
    string* ptr;
  public:
    Example6 (const string& str) : ptr(new string(str)) {}
    ~Example6 () {delete ptr;}
    // move constructor
    Example6 (Example6&& x) : ptr(x.ptr) {x.ptr=nullptr;}
    // move assignment
    Example6& operator= (Example6&& x) {
      delete ptr; 
      ptr = x.ptr;
      x.ptr=nullptr;
      return *this;
    }
    // access content:
    const string& content() const {return *ptr;}
    // addition:
    Example6 operator+(const Example6& rhs) {
      return Example6(content()+rhs.content());
    }
};


int main () {
  Example6 foo ("Exam");
  Example6 bar = Example6("ple");   // move-construction
  
  foo = foo + bar;                  // move-assignment

  cout << "foo's content: " << foo.content() << '\n';
  return 0;
}

There is some part I dont understand :
1.Example6 (Example6&& x) : ptr(x.ptr) {x.ptr=nullptr;}
What is the meaning of x.ptr and why x.ptr must be a nullptr??

2.
1
2
3
4
5
6
Example6& operator= (Example6&& x) {
      delete ptr; 
      ptr = x.ptr;
      x.ptr=nullptr;
      return *this;
}

Same as above, what is the meaning of x.ptr and why x.ptr must be a nullptr??

3.return Example6(content()+rhs.content());
Why can it be just content(), not like sth.content()??

4.foo = foo + bar; // move-assignment
In here it says that this code is a move-assignment, why??
I think it is using operator?
Besides,baz = MyClass(); , this is how move-assignment is written in article

Please explain these to me..

Thanks..
Example6( Example6&& x );
This constructor takes parameter x that is a rvalue reference to type Example6 object.
The x is Example6 object.

Class Example6 has member ptr. We access member 'ptr' of object x with syntax x.ptr.

Example of copy construction:
1
2
3
4
5
6
7
class T {
  U val;
public:
  T( const T& x )
   : val ( x.val )
  {}
};

The member 'val' of constructed object is initialized with value of same member in object 'x', whose copy the constructed object will be.


1
2
3
4
5
Example6::Example6( Example6&& x )
 : ptr(x.ptr)
{
  x.ptr = nullptr;
}

An Example6 object points to a std::string object.
We move content of 'x' into new object.
After construction the new object points to the string object.
The other object (that we refer to as 'x') does still exists, but it cannot point to the string because we did move the string (ownership) to the new object.
We set the pointer to nullptr to clearly show that the pointer no longer points to any object.


What does expression foo + bar return?
@keskiverto

foo + bar return "Example"
Yes, the expression returns a nameless, temporary Example6 object.
In foo = Example6(); the Example6() returns nameless, temporary Example6 object.

In both cases there is assign to 'foo' an rvalue. For that the move assignment is appropriate.

On the:
1
2
3
4
Example6 Example6::operator+( const Example6& rhs )
{
  return Example6( content() + rhs.content() );
}

did you ask why the bold is not more specific?

You can write it more explicitly:
1
2
3
4
Example6 Example6::operator+( const Example6& rhs )
{
  return Example6( this->content() + rhs.content() );
}

But you don't need to. All members of the class object (variables and functions) are implicitly in the scope of a member variable. You did not ask why you can write 'ptr' in:
1
2
3
4
Example6::~Example6 ()
{
  delete ptr;
}

You do need pointer this only when identical names cause ambiguity or masking, or when you want to be more clear for the reader of your code.


PS. The operator+ does not have to be a member function. It could be a standalone function:
1
2
3
4
Example6 operator+( const Example6& lhs, const Example6& rhs )
{
  return Example6( lhs.content() + rhs.content() );
}

@keskiverto

Does it mean that I can only use either copy or move constructor or assignment and how they are use is the same?
What do you mean by "only"?

If you want to construct a new Example6 object and initialize it with existing Example6 object, then you can either copy construct or move construct, depending on details of the situation.

If you want to assign value of Example6 object into another existing Example6 object, then you can either copy assign or move assign, depending on details of the situation.

Assignment is not initialization.
@keskiverto

I mean like can I use copy constructor and move constructor at the same time and can I use copy assignment and move assignment at the same time??
If you do ask:
Can a class have all four members (copy ctor, move ctor, copy assign, move assign)?
Then, yes, it can. See https://en.cppreference.com/w/cpp/language/rule_of_three
Topic archived. No new replies allowed.