An rvalue in C++ is a temporary object or a value that does not have a persistent memory location. Unlike lvalues, rvalues typically appear on the right-hand side of an assignment and are often created during expressions or function calls. Rvalues are not addressable, meaning you cannot take their address with the &
operator, and they are often used as inputs to functions or operations.
#include <iostream>
int main() {
int a = 10; // 'a' is an lvalue, '10' is an rvalue
int b = a + 5; // 'a + 5' is an rvalue
std::cout << "b: " << b << std::endl;
return 0;
}
10
: This is an rvalue because it is a literal that does not refer to any persistent memory location.
a + 5
: This expression is an rvalue because it results in a temporary value that is not stored in a specific memory location. It is used to initialize b
, which is an lvalue.
C++11 introduced rvalue references (denoted by T&&), which allow you to bind to rvalues. Rvalue references are essential for implementing move semantics, which enable the efficient transfer of resources from temporary objects.
#include <iostream>
void process(int&& x) {
std::cout << "Rvalue reference: " << x << std::endl;
}
int main() {
process(10); // 10 is an rvalue, bound to int&&
int a = 20;
// process(a); // Error: 'a' is an lvalue, cannot bind to int&&
process(std::move(a)); // std::move(a) casts 'a' to an rvalue
return 0;
}
int&& x
: The process function takes an rvalue reference as its parameter, meaning it can only bind to rvalues.process(10)
: 10
is an rvalue, so it can be passed to process.std::move(a)
: std::move
is used to cast a (an lvalue) to an rvalue, allowing it to be passed to process.Move semantics leverage rvalues to efficiently transfer resources from temporary objects, avoiding the overhead of copying.
#include <iostream>
#include <string>
class MyClass {
public:
std::string data;
// Constructor
MyClass(const std::string& str) : data(str) {
std::cout << "Constructed\n";
}
// Move Constructor
MyClass(MyClass&& other) noexcept : data(std::move(other.data)) {
std::cout << "Move Constructed\n";
}
};
int main() {
MyClass obj1("Hello, World!");
MyClass obj2(std::move(obj1)); // obj1 is cast to an rvalue using std::move
std::cout << "obj2.data: " << obj2.data << std::endl;
return 0;
}
MyClass(MyClass&& other)
is designed to take an rvalue reference and "move" resources from other to the new object.std::move(obj1)
: Casts obj1
(an lvalue) to an rvalue, allowing the move constructor to be invoked.Rvalues often arise from expressions or temporary objects, such as the return value of a function or the result of an arithmetic operation.
#include <iostream>
int add(int x, int y) {
return x + y; // The result of 'x + y' is an rvalue
}
int main() {
int result = add(5, 10); // 'add(5, 10)' is an rvalue
std::cout << "result: " << result << std::endl;
return 0;
}
x + y
: The result of this expression is an rvalue because it is a temporary value that is returned by the add function.add(5, 10)
: The return value of the add function is an rvalue, which is used to initialize result.You can bind rvalues to const lvalue references, which allows you to pass temporary values to functions without modifying them.
#include <iostream>
void print(const int& x) {
std::cout << "Value: " << x << std::endl;
}
int main() {
print(10); // 10 is an rvalue, but can be bound to 'const int&'
return 0;
}
const int& x
: A const lvalue reference can bind to an rvalue. This allows the function print to accept both lvalues and rvalues without modifying them.print(10)
: Here, 10
is an rvalue, but it is successfully passed to print because x
is a const lvalue reference.&
operator.#include <iostream>
int main() {
int x = 10; // 'x' is an lvalue
int y = x + 5; // 'x + 5' is an rvalue
int* p1 = &x; // OK: 'x' is an lvalue
// int* p2 = &(x + 5); // Error: 'x + 5' is an rvalue, can't take its address
y = 15; // OK: 'y' is an lvalue
return 0;
}
x
is an lvalue, representing a variable with a memory location. You can take its address and modify it.x + 5
is an rvalue, a temporary value. You cannot take the address of an rvalue.std::move
: A utility that converts an lvalue to an rvalue, enabling the use of move semantics.Understanding rvalues and their role in move semantics is fundamental to writing efficient and modern C++ code. Rvalues allow you to take advantage of temporary objects without incurring the cost of unnecessary copying.
Previous Page | Course Schedule | Course Content