目录
- 1、move与forward
- move
- forward
- 2、左值和右值
- 左值
- 右值
- 引用和值类别之间的关系
- 3、
1、move与forward
move
- 语法形式:
std::move<T>(t)
,T 是要转换的对象的类型(通常可以通过模板参数推导自动确定),t 是要被转换(移动)的左值对象; - 应用场景:资源所有权转移
- 1)容器元素移动:当需要高效地将一个容器中的元素移动到另一个容器时可以使用
std::move
,可以减少不必要的拷贝操作;
std::vector<std::string> vec1 = {"apple", "banana", "cherry"}; std::vector<std::string> vec2; vec2 = std::move(vec1);
- 2)函数返回值优化:函数返回一个局部对象时,可以使用std::move来提示编译器进行移动语义而不是拷贝语义,将局部对象的资源所有权直接转移给函数调用者,不用拷贝从而提高性能;
std::vector<int> create_vector() {std::vector<int> v = {1, 2, 3};return std::move(v); }
- 1)容器元素移动:当需要高效地将一个容器中的元素移动到另一个容器时可以使用
forward
- 语法:
std::forward<T>(t)
,T 是一个模板参数指定的类型,t 是一个参数(通常是一个万能引用,即T&&
形式的参数); - 应用场景:完美转发
- 函数模板参数转发:用于在函数模板中实现完美转发,将函数的参数以其原始的值类别(左值或右值)传递给另一个函数。如下,
wrapper函数
可以接收任意函数 f 和任意参数 args ,并且通过std::forward
将 args 以其原始的值类别转发给f。这样,f可以根据参数的实际值类别(左值引用或右值引用)进行最优化的处理,比如对于右值参数可以进行移动操作,对于左值参数可以进行正常的引用操作:
template<typename Func, typename... Args> auto wrapper(Func&& f, Args&&... args) {return f(std::forward<Args>(args)...); }
- 函数模板参数转发:用于在函数模板中实现完美转发,将函数的参数以其原始的值类别(左值或右值)传递给另一个函数。如下,
2、左值和右值
左值
- 左值是指表达式结束后依然存在的持久对象。可以获取它的地址,并且能够对其进行赋值操作;在 C++ 中,变量名就是典型的左值;
- 特性:
- 可寻址性;
- 可赋值性;
右值
- 右值是指表达式结束后就不再存在的临时对象。通常是字面量、临时变量或者是函数返回值等这些不能获取地址,,并且不能对其进行常规赋值操作的对象;
- 特性:
- 临时性;
- 不可赋值性;
引用和值类别之间的关系
- 左值引用:用
&
来表示,它绑定到左值上。例如,int a = 5; int& ref_a=a;
,这里ref_a
是左值引用,它绑定到左值 a上,通过ref_a
可以修改 a 的值; - 右值引用:用
&&
来表示,它主要用于绑定到右值上,如int&& rref = 5
,rref
是右值引用,它绑定到右值5上;- 作用:允许我们对右值进行一些特殊的操作,比如将右值所代表的资源 “窃取” 过来,而不是进行拷贝操作,这在对象构造和赋值等操作中可以提高性能;