1. 程式人生 > >C++中的左值和右值

C++中的左值和右值

左值和右值的定義

在C++中,可以放到賦值操作符=左邊的是左值,可以放到賦值操作符右邊的是右值。有些變數既可以當左值又可以當右值。進一步來講,左值為Lvalue,其實L代表Location,表示在記憶體中可以定址,可以給它賦值(常量const型別也可以定址,但是不能賦值),Rvalue中的R代表Read,就是可以知道它的值。例如: int a=3; a在記憶體中有地址,而3沒有,但是可以read到它的值。 3=4; 這個是錯誤的,因為3的記憶體中沒有地址,不能當作左值。 下面這個語句不容易出錯 a++=3; 這個語句編譯通不過的,原因在於a++是先使用a的值,再給a加1。實現如下:
{
	int tmp=a;
	a=a+1;
	return tmp;
}
++a是右值。 ++a=3; 這個是正確的,++a的實現如下:
{
	a=a+1;
	return &a;
}
顯然++a的效率高。

左值符號&和右值符號&&

左值的宣告符號為&,右值的宣告符號為&&。在C++中,臨時物件不能作為左值,但是可以作為常量引用const &
#include<iostream>
void print_lvalue(int& i)//左值
{
	std::cout << "Lvalue:" << i << std::endl;
}
void print_rvalue(int&& i)//右值
{
	std::cout << "Rvalue:" << i << std::endl;
}

int main()
{
	int i = 0;
	print_lvalue(i);
	print_rvalue(1);
	//print_lvalue(1)會出錯
	//print_lvalue(const int& i)可以使用print_lvalue(1)
	return 0;
}

C++11中的move

有時候我們希望把左值當作右值來使用,例如一個變數的值,不再使用了,希望把它的值轉移出去,C++11中的std::move就為我們提供了將左值引用轉為右值引用的方法。
#include<iostream>
void print_value(int& i)//左值
{
	std::cout << "Lvalue:" << i << std::endl;
}
void print_value(int&& i)//右值
{
	std::cout << "Rvalue:" << i << std::endl;
}

int main()
{
	int i = 10;
	print_value(i);
	print_value(std::move(i));
	return 0;
}

最長用的交換函式
void swap(T& a, T& b)
{
	T tmp = std::move(a);
	a = std::move(b);
	b = std::move(tmp);
}
避免了3次拷貝。 move的本質,只是將引數轉換為右值引用,並沒有移動什麼。因此要實現類關於右值得建構函式和複製操作符。move實現如下:
template <typename T>
decltype (auto) move(T&& param){
	using ReturnType = remove_reference_t<T>&&;
	return static_cast<ReturnType>(param);
}


精確值傳遞

std::forward主要用於模板程式設計中,值傳遞的問題。可以推測引數是左值引用還是右值引用,精確傳遞值。參考這裡: http://blog.csdn.net/zwvista/article/details/6848582