the earliest days of C

An lvalue is an expression e that may appear on the left or on the right hand side of an assignment, whereas an rvalue is an expression that can only appear on the right hand side of an assignment. For example,

int a = 42;
int b = 43;

// a and b are both l-values:
a = b; // ok
b = a; // ok
a = a * b; // ok

// a * b is an rvalue:
int c = a * b; // ok, rvalue on right hand side of assignment
a * b = 42; // error, rvalue on left hand side of assignment

C++

An lvalue is an expression that refers to a memory location and allows us to take the address of that memory location via the & operator. An rvalue is an expression that is not an lvalue.

Examples are:

// lvalues:
//
int i = 42;
i = 43; // ok, i is an lvalue
int* p = &i; // ok, i is an lvalue
int& foo();
foo() = 42; // ok, foo() is an lvalue
int* p1 = &foo(); // ok, foo() is an lvalue

// rvalues:
//
int foobar();
int j = 0;
j = foobar(); // ok, foobar() is an rvalue
int* p2 = &foobar(); // error, cannot take the address of an rvalue
j = 42; // ok, 42 is an rvalue

More example

void PrintName1 (std::string& name){
	std::cout << name << std::endl;
}
void PrintName2 (const std::string& name){
	std::cout << name << std::endl;
} // that's why many function takes const in C++
void PrintName3 (std::string&& name){
	std::cout << name << std::endl;
} // it takes only temporary references.

int main(){
	std::string firstName = "Huijo";
	std::string lastName = "Kim";
	std::string fullName = firstName + lastName; 
	// fullName: lvalue
	// firstName + lastName: rvalue (temporary references)

	printName1(fullName); // it works (it needs lvalue)
	printName1(firstName + lastName); // it doesn't work with temporary rvalue

	printName2(fullName); // it works 
	printName2(firstName + lastName); // it works

	printName3(fullName); // it doesn't work. (can't pass lvalue)
	printName3(firstName + lastName); // it works with rvalue.

I can overload the functions, too.

void PrintName (const std::string& name){
	std::cout << name << std::endl;
} 
void PrintName (std::string&& name){
	std::cout << name << std::endl;
}

it is useful for move semantic.