1.掌握值类别概念
类型与值类别:对于c++表达式可按照两个独立的属性加以识别:类型与值类别。且每个表达式只属于三种值类别的一种左值,右值,将亡值,每个值类别都与某种引用对应。
1.1 lvalue(左值)
左值是具有标识符、可取地址的表达式,通常具有持久状态。
特征:
- 有名称的变量或对象
- 可通过&运算符取地址
- 生命周期通常超出当前表达式
cpp
int x = 5; // x是左值
int* p = &x; // 可以取地址
int& getRef() { return x; }
getRef() = 10; // 函数返回左值引用,是左值[1](@ref)
1.2 prvalue(纯右值)
纯右值是没有标识符的临时对象,通常是字面量或返回非引用的函数调用结果。
特征:
- 通常是临时对象
- 不能取地址
- 用于初始化其他对象
cpp
int x = 42; // 42是纯右值
std::string s = "hello"; // "hello"是纯右值
int getValue() { return 42; }
int y = getValue(); // getValue()返回纯右值[1](@ref)
1.3 xvalue(将亡值)
将亡值是C++11新增的类别,表示有标识符但可以被移动的表达式。
特征:
- 有标识符但生命周期即将结束
- 可以被移动而非复制
- 通常与右值引用相关
cpp
std::string s1 = "hello";
std::string s2 = std::move(s1); // std::move(s1)返回将亡值
struct Data { std::string name; };
Data getData() { return Data{"test"}; }
std::string n = getData().name; // getData().name是将亡值[1](@ref)
三种示例:
cpp
#include<iostream>
using namespace std;
class Int{
int value;
public:
Int(int x=0):value(x){cout<<"Create int: "<<this<<endl;}
Int(const Int&it):value(it.value){cout<<"Copy Create Int: "<<this<<endl;}
Int& operator=(const Int& it){
if(this!=&it)
{
value=it.value;
cout<<"operator=()"<<endl;
}
return *this;
}
~Int(){
cout<<"Destroy Int:"<<this<<endl;
}
void PrintValue()const{
cout<<"value: "<<this->value<<endl;
}
};
Int fun(int x){
Int tmp(x);
return tmp;
}
int main(){
Int a(10);//左值
const Int b(20);//常性左值
Int (20);//右值无名对象
a=fun(20);//fun(20)将亡值
}
运行结果:
Create int: 0x7fffffffdf0c//Int a(10);创建
Create int: 0x7fffffffdf10//const Int b(20);//常性左值创建
Create int: 0x7fffffffdf14//Int (20);//右值无名对象创建
Destroy Int:0x7fffffffdf14//Int (20);//右值无名对象销毁
Create int: 0x7fffffffdf14// Int tmp(x);创建
operator=()//a=fun(20)
Destroy Int:0x7fffffffdf14// Int tmp(x);创建
Destroy Int:0x7fffffffdf10// const Int b(20);//常性左值销毁
Destroy Int:0x7fffffffdf0c//Int a;销毁