移动语义与完美转发
移动语义
1 | // std::move 的实现 |
通过 remove_reference 去掉 T 的引用性质(并不会去掉 cv 限定符),然后给它加上 &&,形成 ReturnType 类型,由于右值引用类型的返回值是右值,因此结果是实参被无条件地转换为右值。
如果没有定义移动构造函数,则使用拷贝构造函数。
std::move 是一个模板函数,用于将对象转换为右值引用。它并不直接对对象、值或内存进行任何实际的移动操作。std::move 的作用是告诉编译器可以“窃取”对象的资源,因为对象不再需要保持其原始状态。
- 对象转换:std::move 将一个左值(通常是一个命名对象)转换为右值引用。这种转换允许你调用对象的移动构造函数或移动赋值运算符。
- 资源转移:在使用 std::move 后,通常会调用对象的移动构造函数或移动赋值运算符,这些函数负责实际的资源转移(如指针、动态内存、文件句柄等)。
- 内存管理:std::move 本身不管理内存。内存的管理和资源的转移由移动构造函数或移动赋值运算符负责。
- std::move 通常用于将左值转换为右值引用,以便能够调用对象的移动构造函数或移动赋值运算符。然而,对于纯右值(即临时对象或字面值),std::move 通常是不必要并且多余的,因为它们本身已经是右值。
完美转发
保留参数的值类别(左值、右值),是否为 const 或 volatile 修饰符,并将其传递给其他函数。
std::forward 的实现
1 | template< class T > |
怎么判断该用 move 还是 forward?
- 对右值引用 move
右值引用只能绑定到右值上,所以可以无条件地将它转换为右值 - 对通用引用 forward
通用引用既能绑定到左值上,也能绑定到右值上,在后一种情况下,我们希望能将它转换为右值 - 在右值引用上调用 std::forward 表现出的行为是正确的,但由于 std::forward 没法自动做类型推导,写出来的代码会比较繁琐;但如果在通用引用上调用 std::move,可能会导致左值被错误地修改,导致异常的行为。
参考资料
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Hymns!