R-value references and move semantics

Hi, I require help in understanding what's the purpose of the program below and what it does. I can't seem to understand what it is trying to do. There are some move semantics and all that but it is really hard for me to understand it since I am new to C++.. This program is related to the topic move semantics and r-value references.
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <iostream>
#include <map>
#include <vector>

// ============== Interface ====================================================

class RuntimeFibonacci
{
public:
	using key = unsigned char;
	using value = unsigned long long int;
	using map = std::map<key, value>;

	RuntimeFibonacci();
	void reset(bool clear = true);

	// Calcuates the result and keeps intermediate values for access.
	value calculate(key n) &;

	// Calcuates the result; resets intermediate values as nobody will need to
	// access them later.
	value calculate(key n) &&;

	// Returns a collection of intermediate values.
	const std::vector<value> intermediates() &;

	// You need lvalue object to calculate, then access intermediate values.
	const std::vector<value> intermediates() && = delete;

private:
	map _intermediates;
};

// ============== Implementation ===============================================

RuntimeFibonacci::RuntimeFibonacci()
{
	reset(false);
}
void RuntimeFibonacci::reset(bool clear)
{
	if (clear)
	{
		std::cout << "reset" << std::endl;
		_intermediates.clear();
	}
	_intermediates[0] = 1;
	_intermediates[1] = 1;
}
RuntimeFibonacci::value RuntimeFibonacci::calculate(RuntimeFibonacci::key n) &&
{
	value result = calculate(n);
	// Nobody will be able to access intermediate values, so clear memory.
	reset();
	return result;
}
RuntimeFibonacci::value RuntimeFibonacci::calculate(RuntimeFibonacci::key n) &
{
	map::const_iterator intermediate = _intermediates.find(n);
	if (intermediate == _intermediates.end())
	{
		_intermediates[n] =
			calculate(static_cast<key>(n - 1)) +
			calculate(static_cast<key>(n - 2));
		return _intermediates[n];
	}
	else
	{
		return intermediate->second;
	}
}
const std::vector<RuntimeFibonacci::value> RuntimeFibonacci::intermediates() &
{
	std::vector<value> results;
	for (const map::value_type& i : _intermediates)
	{
		results.push_back(i.second);
	}
	return results;
}

// ============== Use case =====================================================

RuntimeFibonacci getFibonacci()
{
	return RuntimeFibonacci{};
}

void testLvalue()
{
	RuntimeFibonacci fib = getFibonacci();
	std::cout << fib.calculate(10) << std::endl;
	for (const RuntimeFibonacci::value& i : fib.intermediates())
	{
		std::cout << " " << i << std::endl;
	}
}

void testRvalue()
{
	std::cout << getFibonacci().calculate(10) << std::endl;

	// The code below does not work. You are not allowed to access intermediate
	// values without running the calculations first.
/*
	for (const RuntimeFibonacci::value& i : getFibonacci().intermediates())
	{
		std::cout << " " << i << std::endl;
	}
*/
}

int main()
{
	testLvalue();
	std::cout << "---------------" << std::endl;
	testRvalue();
}
I assume you can figure out that it's calculating fibonacci numbers, so your question is presumably about the & and && notation at the end of some member-function declarations. These are called "reference qualifiers".

The & at the end means that the implicit object is a lvalue reference.

The && means that the implicit object is an rvalue reference. (But *this is always an lvalue inside the function.)

Without & or && the implicit object is an lvalue reference that is allowed to bind to an rvalue.

So if the object that calculate is called on is a temporary object (as in TestRValue), then the && version will be called. Why the programmer thought it useful to clear the object's state is a mystery. I don't see the point. Normally that's something you would do when you move from an object, reseting its state to something reasonable after its guts have been ripped out.

BTW, the 10th fibonacci number is 55 not 89, so it gets the wrong answer.

https://www.google.com/search?q=c%2B%2B+reference+qualifier
Last edited on
Topic archived. No new replies allowed.