当前位置:网站首页>(P40-P41)move资源的转移、forward完美转发
(P40-P41)move资源的转移、forward完美转发
2022-06-12 08:01:00 【喜欢打篮球的普通人】
1.move
在 C++11 添加了右值引用,并且不能使用左值初始化右值引用,如果想要使用左值初始化一个右值引用需要借助 std::move () 函数,使用std::move方法可以将左值转换为右值。(可以将左值、左值引用、右值引用转换为右值(STL源码返回的是一个将亡值T&&))
使用这个函数并不能移动任何东西,而是和移动构造函数一样都具有移动语义,将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存拷贝。
从实现上讲,std::move 基本等同于一个类型转换:static_cast<T&&>(lvalue);,函数原型如下:
template<class _Ty>
_NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) _NOEXCEPT
{
// forward _Arg as movable
return (static_cast<remove_reference_t<_Ty>&&>(_Arg));
}
- eg:
class Test
{
public:
Test(){
}
......
}
int main()
{
Test t;
//使用左值初始化右值引用,因此语法是错误的
Test && v1 = t; // error
//使用 move() 函数将左值转换为了右值,这样就可以初始化右值引用了。
Test && v2 = move(t); // ok
return 0;
}
- eg:假设一个临时容器很大,并且需要将这个容器赋值给另一个容器,就可以执行如下操作:
list<string> ls;
ls.push_back("hello");
ls.push_back("world");
......
list<string> ls1 = ls; // 需要拷贝, 效率低
list<string> ls2 = move(ls);
- 解释:
如果不使用 std::move,拷贝的代价很大,性能较低。使用 move 几乎没有任何代价,只是转换了资源的所有权。如果一个对象内部有较大的堆内存或者动态数组时,使用 move () 就可以非常方便的进行数据所有权的转移。
另外,也可以给类编写相应的移动构造函数(T::T(T&& another)),和具有移动语义的赋值函数(T&& T::operator=(T&& rhs)),在构造对象和赋值的时候尽可能的进行资源的重复利用,因为它们都是接收一个右值引用参数。
2.forward
右值引用类型是独立于值的,一个右值引用作为函数参数的形参时,在函数内部转发该参数给内部其他函数时,它就变成一个左值(左值引用更好理解些?),并不是原来的类型了。
如果需要按照参数原来的类型转发到另一个函数,可以使用 C++11 提供的 std::forward () 函数,该函数实现的功能称之为完美转发。
- 函数原型
// 函数原型
template <class T> T&& forward (typename remove_reference<T>::type& t) noexcept;
template <class T> T&& forward (typename remove_reference<T>::type&& t) noexcept;
// 精简之后的样子
std::forward<T>(t);
- 用法:
当T为左值引用类型时,t将被转换为T类型的左值
当T不是左值引用类型时,t将被转换为T类型的右值
- eg:
#include <iostream>
using namespace std;
template<typename T>
void printValue(T& t)
{
cout << "l-value: " << t << endl;
}
template<typename T>
void printValue(T&& t)
{
cout << "r-value: " << t << endl;
}
template<typename T>
void testForward(T&& v)
{
printValue(v);
printValue(move(v));
printValue(forward<T>(v));
cout << endl;
}
int main()
{
/* testForward(520); 函数的形参为未定引用类型 T&&,实参为右值,初始化后被推导为一个右值引用 printValue(v); 已命名的右值 v,编译器会视为左值处理,实参为左值(准确说是左值引用) printValue(move(v)); 已命名的右值编译器会视为左值处理,通过 move 又将其转换为右值,实参为右值 printValue(forward<T>(v));forward 的模板参数为右值引用,最终得到一个右值,实参为 ``右值` */
testForward(520);
int num = 1314;
/* testForward(num); 函数的形参为未定引用类型 T&&,实参为左值,初始化后被推导为一个左值引用 printValue(v); 实参为左值(住准确说是左值引用) printValue(move(v)); 通过 move 将左值转换为右值,实参为右值 printValue(forward<T>(v));forward 的模板参数为左值引用,最终得到一个左值引用,实参为左值 */
testForward(num);
/* testForward(forward<int>(num));forward 的模板类型为 int,最终会得到一个右值,函数的形参为未定引用类型 T&& 被右值初始化后得到一个右值引用类型 printValue(v); 已命名的右值 v,编译器会视为左值处理(准确说是左值引用),实参为左值 printValue(move(v)); 已命名的右值编译器会视为左值处理,通过 move 又将其转换为右值,实参为右值 printValue(forward<T>(v));forward 的模板参数为右值引用,最终得到一个右值,实参为右值 */
testForward(forward<int>(num));
/* testForward(forward<int&>(num));forward 的模板类型为 int&,最终会得到一个左值,函数的形参为未定引用类型 T&& 被左值初始化后得到一个左值引用类型 printValue(v); 实参为左值(准确说是左值引用) printValue(move(v)); 通过 move 将左值转换为右值,实参为右值 printValue(forward<T>(v));forward 的模板参数为左值引用,最终得到一个左值,实参为左值 */
testForward(forward<int&>(num));
/* testForward(forward<int&&>(num));forward 的模板类型为 int&&,最终会得到一个右值,函数的形参为未定引用类型 T&& 被右值初始化后得到一个右值引用类型 printValue(v); 已命名的右值 v,编译器会视为左值处理(准确说是左值引用),实参为左值 printValue(move(v)); 已命名的右值编译器会视为左值处理,通过 move 又将其转换为右值,实参为右值 printValue(forward<T>(v));forward 的模板参数为右值引用,最终得到一个右值,实参为右值 */
testForward(forward<int&&>(num));
return 0;
}
- 测试:

#include <iostream>
using namespace std;
template<typename T>
void printValue(T& t)
{
cout << "l-value: " << t << endl;
}
//&& 是未定义类型的引用
template<typename T>
void printValue(T&& t)
{
cout << "r-value: " << t << endl;
}
//&& 是未定义类型的引用
template<typename T>
void testForward(T && v)
{
printValue(v);
printValue(move(v));
printValue(forward<T>(v));
cout << endl;
}
int main()
{
testForward(520);
int num = 1314;
testForward(num);
testForward(forward<int>(num));
testForward(forward<int&>(num));
testForward(forward<int&&>(num));
return 0;
}
- 参考:转移和完美转发
边栏推荐
- Principes et exemples de tâches OpenMP
- C # hide the keyboard input on the console (the input content is not displayed on the window)
- Compiling principle on computer -- function drawing language (II): lexical analyzer
- 2021.10.24-25 scientific research log
- Latex usage problems and skills summary (under update)
- NaiveBayes function of R language e1071 package constructs naive Bayes model, predict function uses naive Bayes model to predict and reason test data, and table function constructs confusion matrix
- 电脑连接上WiFi但是上不了网
- Procedure execution failed 1449 exception
- R language uses rstudio to save visualization results as PDF files (export--save as PDF)
- S-msckf/msckf-vio technical route and code details online blog summary
猜你喜欢

Three data exchange modes: line exchange, message exchange and message packet exchange

Derivation of Poisson distribution

Classic paper review: palette based photo retrieval

Topic 1 Single_Cell_analysis(2)

记录谷粒商城踩坑(一)

Servlet advanced

Explanation and explanation on the situation that the volume GPU util (GPU utilization) is very low and the memory ueage (memory occupation) is very high during the training of pytoch

Servlet

Some summaries of mathematical modeling competition in 2022

『Three.js』辅助坐标轴
随机推荐
C # push box
Meter Reading Instrument(MRI) Remote Terminal Unit electric gas water
Leetcode notes: Weekly contest 276
Explanation and explanation on the situation that the volume GPU util (GPU utilization) is very low and the memory ueage (memory occupation) is very high during the training of pytoch
Leetcode notes: biweekly contest 69
Leetcode notes: Weekly contest 275
Numerical calculation method chapter5 Direct method for solving linear equations
电脑连接上WiFi但是上不了网
C # hide the keyboard input on the console (the input content is not displayed on the window)
Topic 1 Single_ Cell_ analysis(4)
DUF:Deep Video Super-Resolution Network Using Dynamic Upsampling Filters ...阅读笔记
Cmake can't find the solution of sophus
The latest hbuilderx editing uni app project runs in the night God simulator
802.11 protocol: wireless LAN protocol
Leetcode notes: biweekly contest 70
记录谷粒商城踩坑(一)
Database connection pool and dbutils tool
How to standardize the creation of a pytorch project
Process terminated
Vision Transformer | CVPR 2022 - Vision Transformer with Deformable Attention