大话C++之:左右值引用和std::move
在C++11引入右值引用后,一直对其使用缺乏深入理解,特别是结合std::move移动语义。恰逢最近工作里有相关优化代码使用到,可以趁机会重新学习,加深理解。
什么是左值和右值
从命名来理解,既然命名区分左右,左右值是相对于赋值号“=”来作锚点。
左值(LValue):可以位于等号左边,有持久的内存地址,可以取地址
右值(RValue): 只能位于等号右边,无法取地址
1.1 左值
int x = 1;
x位于等号左侧,并且可以过能&取地址,所以为左值
struct Foo {
Foo(int id = 0) {
id_ = id;
}
int id_;
};
Foo foo = Foo();
如上例,foo位于等号左侧,并且可以通过&取址,则为左值
1.2 右值
int y = 1;
1位于等号右侧,为立即数,不能通过&取地址,所以为右值
struct Foo {
Foo(int id = 0) {
id_ = id;
}
int id_;
};
Foo foo = Foo();
那么Foo()是什么值呢?按上述推理不难得出是右值。
对于左值右值的概念,大体可以这么理解,关键两个条件是:位置和是否能取址。
接下来我们了解一下左值引用和右值引用
什么是左值引用和右值引用
引用的本质是别名,通过引用可以修改它所绑定变量的值。
2.1 左值引用
左值引用是一种引用类型(废话),是变量的别名,其实就是通过指针实现的语法糖。
它可以绑定变量或者对象上,左值引用允许我们通过引用来访问和修改它所绑定的对象。
左值引用,顾名思义,可以指是左值的引用,能指向左值。
int x = 10; // 定义一个整数变量 x
int& ref_x = x; // 定义一个左值引用 ref_x,它引用变量 x
int& ref_y = 10; // 左值引用指向了右值,编译不通过
在这个例子中,我们定义了一个整数变量 x 和一个左值引用 ref_x。ref_x 引用了变量 x,所以我们可以通过 ref_x 来访问和修改 x 的值。
需要强调的是:左值引用必须在定义时进行初始化,且在其生命周期内不能重新绑定到其他对象上。
ref_y作为左值引用不能指右值,但是!const的左传引用可以指向右值。
const int& ref_y = 10; // const左值引用指向了右值,编译通过
由于const左值引用不会修改绑定的值,因此它可以指向右值。