Trying to understand rvalue references and move semantics better

Before I start writing code that uses rvalue references and move semantics I want to make sure that I fully understand it.

I read all of the pages from the following link:

http://thbecker.net/articles/rvalue_references/section_01.html

which was recommended in Nicolai M. Josuttis's book "The C++ Standard Library: A Tutorial and Reference"

And the entire Chapter 5. Rvalue References, Move Semantics, and Perfect Forwarding from "Effective Modern C++" by Scott Meyers.

A wrote this little example to help me understand.

May you please look over my code and tell my whether I'm using the Standard Library facilities correctly?

Don't get overwhelmed by the number of lines of code, most of it is just print statements.

Basically what this code does is type Container is composed of an object of type A. The point of type Container is to move an object of type A (into) Container's data member and to move (out of) Container's data member into another variable.

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <utility>

class A
{
public:
	A(int arg) : data{arg} { std::cout << "A::A()" << '\n'; }
	~A() { std::cout << "A::~A(), data == " << data << '\n'; }
	A(const A& other) { std::cout << "A::A(const A&)" << '\n'; data = other.data; }
	A(A&& other) { std::cout << "A::A(A&&)" << '\n'; data = other.data; other.data = 0; }
	A& operator=(const A& other) { std::cout << "A& A::operator=(const A&)" << '\n'; data = other.data; return *this; }
	A& operator=(A&& other) { std::cout << "A& A::operator=(A&& other)" << '\n';  data = other.data;  other.data = 0; return *this; }
	
	int data;
};

class Container
{
public:
	A&& release_ownership()
	{
		std::cout << "Entering Container::release_ownership()" << '\n';
		obj.data = 10;
		std::cout << "Container::obj.data == " << obj.data << '\n';
		std::cout << "Exiting Container::release_ownership()" << '\n';
		return std::move(obj);
	}
	
	void acquire_ownership(A&& arg)
	{
		std::cout << "Entering Container::acquire_ownership()" << '\n';
		obj = std::move(arg);
		std::cout << "Exiting Container::acquire_ownership()" << '\n';
	}
	
	A obj{5};
};

int main()
{
	std::cout << "Entering main()" << '\n';
	std::cout << "Before declaring Container c;" << '\n';
	Container c;
	std::cout << "After declaring Container c;" << '\n';
	std::cout << "Before calling c.release_ownership()" << '\n';
	A local1{std::move(c.release_ownership())};
	std::cout << "After calling c.release_ownership()" << '\n';
	std::cout << "local1.data == " << local1.data << '\n';
	std::cout << "c.obj.data == " << c.obj.data << '\n';
	
	std::cout << "\n\n";
	
	std::cout << "Before declaring A local2;" << '\n';
	A local2(3);
	std::cout << "After declaring A local2;" << '\n';
	std::cout << "local2.data == " << local2.data << '\n';
	std::cout << "Before calling c.acquire_ownership()" << '\n';
	c.acquire_ownership(std::move(local2));
	std::cout << "After calling c.acquire_ownership()" << '\n';
	std::cout << "local2.data == " << local2.data << '\n';
	std::cout << "c.obj.data == " << c.obj.data << '\n';
	std::cout << "Exiting main()" << '\n';
	
	return 0;
}


Output:

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
Entering main()
Before declaring Container c;
A::A()
After declaring Container c;
Before calling c.release_ownership()
Entering Container::release_ownership()
Container::obj.data == 10
Exiting Container::release_ownership()
A::A(A&&)
After calling c.release_ownership()
local1.data == 10
c.obj.data == 0
 
 
Before declaring A local2;
A::A()
After declaring A local2;
local2.data == 3
Before calling c.acquire_ownership()
Entering Container::acquire_ownership()
A& A::operator=(A&& other)
Exiting Container::acquire_ownership()
After calling c.acquire_ownership()
local2.data == 0
c.obj.data == 3
Exiting main()
A::~A(), data == 0
A::~A(), data == 10
A::~A(), data == 3
Last edited on
Well, everything looks fine. Anything you need help with?

Althought you do not need move on line 46: release_ownership() already casts variable to rvalue reference, you do not need additional cast here.
@MiiNiPaa

Thanks for the reply!

Well there's nothing I need help with, yet. I just wanted to know whether I'm doing things the right way.
Topic archived. No new replies allowed.