C++【move 与 forward】

C++11中std::move、std::forward、左右值引用、移动构造函数的测试问题 主要介绍了C++11中std::move、std::forward、左右值引用、移动构造函数的测试,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 立即下载

一. move

关于 lvaue 和 rvalue,在 c++11 以前存在一个有趣的现象:T&  指向 lvalue (左传引用), const T& 既可以指向 lvalue 也可以指向 rvalue。但却没有一种引用类型,可以限制为只指向 rvalue。这乍看起来好像也不是很大的问题,但实际与看起来不一样,右值引用的缺失有时严重限制了我们在某些情况下,写出更高效的代码。举个粟子,假设我们有一个类,它包含了一些资源:

class holder
{
     public:
 
          holder()
          {
               resource_ = new Resource();
          }
          ~holder()
          {
               delete resource_;
          }

          holder(const holder& other)
          {
                resource_ = new Resource(*other.resource_);
          }

          holder(holder& other)
          {
                resource_ = new Resource(*other.resource_);
          }

          holder& operator=(const holder& other)
          {
                delete resource_;
                resource_ = new Resource(*other.resource_);
                return *this;
          }
           holder& operator=(holder& other)
          {
                delete resource_;
                resource_ = new Resource(*other.resource_);
                return *this;
          }
          private:

               Resource* resource_;
};

这是个 RAII 类,构造函数与析构函数分别负责资源的获取与释放,因此也相应处理了拷贝构造函数 (copy constructor) 和重载赋值操作符 (assignment operator),现在假设我们这样来使用这个类。

// 假设存在如下一个函数,返回值为 holder 类型的临时变量
holder get_holder() { return holder(); }

holder h;
foo(h);

h = get_holder();

理想情况下(不考虑返回值优化等因素),这一小段代码的最后一条语句做了如下三件事情:

1)  销毁 h 中的资源。

2)  拷由 get_holder() 返回的资源。

3)  销毁 get_holder() 返回的资源。

显然我们可以发现这些事情中有些是不必要的:假如我们可以直接交换 h 中的资源与 get_holder() 返回的对象中的资源,那我们就可以直接省略掉第二步中的拷贝动作了。而这里之所以交换能达到相同的效果,是因为 get_holder() 返回的是临时的变量,是个 rvalue,它的生命周期通常来说很短,具体在这里,就是赋值语句完成之后,任何人都没法再引用该 rvalue,它马上就要被销毁了,它所包含的资源也无法再被访问。而如果是像下面这样的用法,我们显然不可以直接交换两者的资源:

holder h1;
holder h2;

h1 = h2;

foo(h2);

因为 h2 是个 lvalue,它的生命周期较长,在赋值语句结束之后,变量仍然存在,还有可能要被别的地方使用。因此,rvalue 的短生命周期给我们提供了在某些情况优化代码的可能。但这种可能在 c++11 以前是没法利用到的,因为我们没法在代码中对 rvalue 区别对待:在函数体中,程序员无法分辨传进来的参数到底是不是 rvalue,我们缺少一个 rvalue 的标记。

回忆一下,T& 指向的是 lvalue,而 const T& 指向的,却可能是 lvalue 或 rvalue,我们没有任何方式能够确认当前参数是不是 rvalue!为了解决这个问题,c++11 中引入了一个新的引用类型: some_type_t &&,这种引用指向的变量是个 rvalue, 有了这个引用类型,我们前面提到的问题就迎刃而解了。

class holder
{
     public:
 
          holder()
          {
               resource_ = new Resource();
          }
          ~holder()
          {
               if (resource_) delete resource_;
          }

          holder(const holder& other)
          {
                resource_ = new Resource(*other.resource_);
          }

          holder(holder& other)
          {
                resource_ = new Resource(*other.resource_);
          }
          
          holder(holder&& other)
          {
                resource_ = other.resource_;
                other.resource_ = NULL;
          }

          holder& operator=(const holder& other)
          {
                delete resource_;
                resource_ = new Resource(*other.resource_);
          return *this;
          }

          holder& operator=(holder& other)
          {
                delete resource_;
                resource_ = new Resource(*other.resource_);
                return *this;
          }

          holder& operator=(holder&& other)
          {
                std::swap(resource_, other.resource_);
                return *this;
          }

          private:

               Resource* resource_;
};

因为有了右值引用,当我们再写如下代码的时候:

holder h1;
holder h2;

h1 = h2; // 调用operator(holder&);
h1 = get_holder(); // 调用operator(holder&&)

编译器就能根据当前参数的类型选择相应的函数,显然后者的实现是更高效的。写到里,有的人也许会有疑问:  some_type_t&& ref  指向的是右值(右值引用),那 ref 本身在函数内是左值还是右值?具体来说就是如下代码中,第三行所调用的是 operator=(holder&) 还是 operator=(holder&&)?

1 holder& operator=(holder&& other)
2 {
3       holder h = other;4       return *this;
5 }

这个问题的本质还是怎么区分 rvalue? c++11 中对 rvalue 作了明确的定义:

Things that are declared as rvalue reference can be lvalues or rvalues. The distinguishing criterion is: if it has a name, then it is an lvalue. Otherwise, it is an rvalue.

如果一个变量有名字,它就是 lvalue,否则,它就是 rvalue。根据这样的定义,上面的问题中,other 是有名字的变量(变量的类型是右值引用),因此是个 lvalue,因此第3行调用的是 operator=(holder&)。好了说了这么久,一直没说到 move(),现在我们来给出它的定义:

c++11 中的 move() 是这样一个函数,它接受一个参数,然后返回一个该参数对应的右值引用.

就这么简单!你甚至可以暂时想像它的原型是这样的(当然是错的,正确的原型我们后面再讲)。

T&& move(T& val);

那么,这样一个 move() 函数,它有什么使用呢?用处大了!回到前面例子,我们用到了 std::swap() 这个函数,回想一下以前我们是怎么想来实现 swap 的呢?

1 void swap(T& a, T& b)
2 {
3     T tmp = a;
4     a = b;
5     b = tmp;
6 }

想像一下,如果 T 是我们之前定义的 holder,这里面就多做了很多无用功,每一个赋值语句,就有一次资源销毁以及一次拷贝!而事实上我们只是要交换 a 与 b 的内容,中间的拷贝都是额外的负担,完全可以考虑消除这些无用功。

1 void swap(T& a, T& b)
2 {
3      T tmp = move(a);
4      a = move(b);
5      b = move(tmp);
6 }

这样一来,如果 holder 提供了 operator=(T&&) 重载,上述操作就相当于只是交换了三次指针,效率大大提升!move() 使得程序员在有需要的情况下能把 lvalue 当成右值来对待。

二. forward()

1. 转发问题

除了 move() 语义之外,右值引用的提出还解决另一个问题:完美转发 (perfect forwarding),转发问题针对的是模板函数,这些函数主要处理的是这样一个问题:假设我们有这样一个模板函数,它的作用是:缓存一些 object,必要的时候创建新的。

template<class TYPE, class ARG>
TYPE* acquire_obj(ARG arg)
{
     static list<TYPE*> caches;
     TYPE* ret;

     if (!caches.empty())
     {
          ret = caches.pop_back();
          ret->reset(arg);
          return ret;
     }

     ret = new TYPE(arg);
     return ret;
}

这个模板函数的作用简单来说,就是转发一下参数 arg 给 TYPE 的 reset() 函数和构造函数,除此它就没再干别的事情,在这个函数当中,我们用了值传递的方式来传递参数,显然是比较低效的,多了次没必要的拷贝,于是我们准备改成传递引用的方式,同时考虑到要能接受 rvalue 作为参数,最后做出艰难的决定改成如下样子:

template<class TYPE, class ARG>
TYPE* acquire_obj(const ARG& arg)
{
    //...
}

但这样写很不灵活:

1) 首先,如果 reset() 或 TYPE 的构造函数不接受 const 类型的引用,那上述的函数就不能使用了,必须另外提供非 const TYPE& 的版本,参数一多的话,很麻烦。

2) 其次,如果 reset() 或 TYPE 的构造函数能够接受 rvalue 作为参数的话,这个特性在 acquire_obj() 里头也永远用不上。

其中1) 好理解,2) 是什么意思?

2) 说的是这样的问题,即使 TYPE 存在 TYPE(TYPE&& other) 这样的构造函数,它在上述 acquire_obj() 中也永远不会被调用,原因是在 acquire_obj() 中,传递给 TYPE 构造函数的,永远是 lvalue(因为 arg 有名字),哪怕外面调用 acquire_obj() 时,用户传递进来的是 rvalue,请看如下示例:

holder get_holder();

holder* h = acquire_obj<holder, holder>(get_holder());

虽然在上面的代码中,我们传递给 acquire_obj() 的是一个 rvalue,但是在 acuire_obj() 内部,我们再使用这个参数时,它却永远是 lvalue,因为它有名字 --- 有名字的就是 lvalue。acquire_obj() 这个函数它的基本功能本来只是传发一下参数,理想状况下它不应该改变我们传递的参数的类型:假如我们传给它 lvalue,它就应该传 lvalue 给 TYPE,假如我们传 rvalue 给它,它就应该传 rvalue 给 TYPE,但上面的写法却没有做到这点,而在 c++11 以前也没法做到。forward() 函数的出现,就是为了解决这个问题。

forward() 函数的作用:它接受一个参数,然后返回该参数本来所对应的类型的引用。

2. 两个原则

C++11 引入了右值引用的符号:&&,从前面一路看下来,可能有人已经习惯了一看到 T&& 就以为这是右值引用,这确实很容易误解,但事实是,T&&  为右值引用只有当 T 为一个具体的类型时才成立,而如果 T 是推导类型时(如模板参数, auto 等)这就不一定了,比如说如下代码中的 ref_int,根据定义这个变量的类型必定是一个右值引用,但模板函数 func 的参数 arg 则不定是右值引用了,因为此时 T 是一个推导类型。

int&& ref_int = get_int();

template <typename T>
void func(T&& arg)
{
}

Scott Meyer 曾对 T&& 这个特殊的东西作过一个专门的演讲,他称 T&& 为 universal reference(更新:不久后,c++ 社区认为叫作 forwarding reference 更准确),Universal reference 被实例化后(instantiate),即可能是一个左值引用,也可能是一个右值引用,具体来说,对于推导类型 T,  如果 T&& v  被一个左值初始化,那 v 就是左值引用,如果 v 被右值初始化,那它就是右值引用,很神奇!实现这是怎么做到的呢?主要来说,在参数类型推导上,c++11 加入了如下两个原则:

原则 (1):

引用折叠原则 (reference collapsing rule),注意,以下条目中的 T 为具体类型,不是推导类型。

1)  T& & (引用的引用) 被转化成 T&.

2)T&& & (rvalue的引用)被传化成 T&.

3)  T& && (引用作rvalue) 被转化成 T&.

4)  T&& && 被转化成 T&&.

原则 (2):

对于以 rvalue reference 作为参数的模板函数,它的参数推导也有一个特殊的原则,假设函数原型为:

template<class TYPE, class ARG>
TYPE* acquire_obj(ARG&& arg);

1) 如果我们传递 lvalue 给 acquire_obj(),则 ARG 就会被推导为 ARG&,因此如下代码的第二行,acquire_obj 被推导为: TYPE* acquire_obj(ARG& &&)。

1 ARG arg;
2 acquire_obj(arg);

然后根据前面说的折叠原则,我们得到原型如下的函数: TYPE* acquire_obj(ARG&);

2) 如果我们如下这样传递 rvalue 给 acquire_obj(),则 ARG 就会被推导为 ARG。

acquire_obj(get_arg()); 

最后,模板函数实例化为原型如下的函数:TYPE* acquire_obj(ARG&&); 

综上讨论可见,原则 2 其实是有些令人讨厌的,它与一般模板函数的参数类型推导并不一致,甚至可以说有些相背(主要在于 top level cv removal principle),这些随处可见的例外增加了语言的复杂性,加大了学习和记忆的难度,是如此令人讨厌,但在 c++ 中这种现象又那么常见,真是无奈。

3.结论

有了以上两个原则,现在我们可以给出理想的 acquire_obj() 原型,以及 forward() 原型。

template<class TYPE>
TYPE&& forward(typename remove_reference<TYPE>::type& arg)
{
   return static_cast<TYPE&&>(arg);
}

template<class TYPE, class ARG>
TYPE* acquire_obj(ARG&& arg)
{
   return new TYPE(forward<ARG>(arg));
}

注意上面 forward 的原型,这里只给出了参数是左值引用的原型,其实还有一个接受右值引用的重载(用来处理传入的参数是右值的情况)。另外需要额外注意的是,forward 的模板参数类型 TYPE 与该函数的参数类型并不直接等价,因此无法根据传入的参数推导模板参数,使得调用方必需显式地指定模板参数的类型,如: forward<ARG>(xx),否则会有编译错误。

下面我们验证一下,上述函数是否能正常工作,假如我们传给 acquire_obj() 一个 lvalue,根据上面说的模板推导原则 2,ARG 会被推导为 ARG&,我们得到如下函数:

TYPE* acquire_obj(ARG& && arg)
{
   return new TYPE(forward<ARG&>(arg));
}

以及相应的 forward()函数。

TYPE& && 
forward(typename remove_reference<TYPE&>::type& arg)
{
   return static_cast<TYPE& &&>(arg);
}

再根据折叠原则,我们得到如下的函数:

TYPE* acquire_obj(ARG& arg)
{
   return new TYPE(forward<ARG&>(arg));
}

以及相应的forward()函数。

TYPE& forward(typename remove_reference<TYPE&>::type& arg)
{
   return static_cast<TYPE&>(arg);
}

 所以,最后在 acquire_obj 中,forward 返回了一个 lvalue 引用, TYPE 的构造函数接受了一个 lvaue 引用, 这正是我们所想要的。 而假如我们传递给 acquire_obj 一个 rvalue 的参数,根据模板推导原则,我们知道 ARG 会被推导为 ARG,于是得到如下函数: 

TYPE* acquire_obj(ARG&& arg)
{
   return new TYPE(forward<ARG>(arg));
}

以及相应的 forward() 函数。

TYPE&& forward(typename remove_reference<TYPE>::type& arg)
{
   return static_cast<TYPE&&>(arg);
}

最后 acquire_obj() 中 forward() 返回了一个 rvalue reference,TYPE 的构造函数接受了一个 rvalue,也是我们所想要的。可见,上面的设计完成了我们所想要的功能,这时的 acquire_obj() 函数才是完美的转发函数。

三.move的原型

显然,move() 必定是一个模板函数,它的参数类型推导完全遵循前面提到两个原则,这就是为何我把它的原型放到现在才写出来,用心良苦啊。

template<class T> 
typename remove_reference<T>::type&&
std::move(T&& a)
{
  typedef typename remove_reference<T>::type&& RvalRef;
  return static_cast<RvalRef>(a);
}

根据模板推导原则和折叠原则,我们很容易验证,无论是给 move 传递了一个 lvalue 还是 rvalue,最终返回的,都是一个rvalue reference。而这正是 move 的意义,得到一个 rvalue 的引用。看到这里有人也许会发现,其实就是一个 cast 嘛,确实是这样,直接用 static_cast 也是能达到同样的效果,只是 move 更具语义罢了。

摘自:https://www.cnblogs.com/catch/p/3507883.html

Python 爬虫高级实战:HTTPS 证书忽略与代理抓包配置 本文深入解析了HTTPS加密与SSL证书校验机制在爬虫开发中的核心问题及解决方案。文章首先剖析了HTTPS协议架构和证书校验流程,指出爬虫开发中常见的证书异常场景及其负面影响。随后详细介绍了Python主流请求库(requests、httpx、aiohttp)的证书忽略配置方法,包括同步/异步模式下的实现方案。针对代理环境,文章系统比较了HTTP、HTTPS、SOCKS5等代理类型的特性差异,并提供了完整的代理配置示例。特别对中间人抓包场景,阐述了Mitmproxy的工作原理和配置要点。最后提出了工程级爬虫 阅读详情

相关推荐

OCS2 移动机械臂深度解析:ocs2_mobile_manipulator 与 ocs2_mobile_manipulator_ros 源码全拆解

摘要:本文深入解析OCS2移动机械臂MPC控制框架的两个核心工具包。ocs2_mobile_manipulator负责算法建模,通过MobileManipulatorInterface统一构建最优控制问题,支持4种机械臂模型并实现自动维度推导;ocs2_mobile_manipulator_ros负责ROS集成,包含MPC求解、虚拟跟踪等4个核心节点。文章详细剖析了工具包分工、最优控制建模架构(含动力学、代价约束设计)、ROS运行管线、参数配置映射,并提供了高效的源码阅读顺序建议,帮助开发者快速掌握移动机械

m0_73309445的博客 655

C++ Move与Forward实现原理

这部分可重点参考《C++ Primer 》第5版 P608-P614,写的很透彻。 Forward的使用 #include<iostream> #include<string> #include<vector> using namespace std; template<typename T> void print(T& t) { c...

会飞的徐公明 5406

RK3588极速成功部署YOLO26完整全链条:从pt导出、ONNX转换到rknn-toolkit-lite2落地与CMA内存优化

帮助你顺利完成pt模型到瑞星微3588上rknn模型的高效部署

昆兰.沃斯 的博客 532

C++:move,带你从根本理解move函数是什么

一: std::move 这个C++专栏都到第三篇博客了,希望大家看完有用的话可以康康博主往期的博客,有兴趣的话可以关注一下,嘻嘻,不说了,说到move离不开的就是,移动语义和值类型,那我们就从值类型先入手吧! 1.值类型(value category) ...

qq_51568363的博客 3万+

别再手动算LLC了!用Mathcad 15分钟搞定谐振参数与增益曲线(附已验证产品案例)

本文详细介绍了如何利用Mathcad在15分钟内高效完成LLC谐振变换器的参数计算与增益曲线绘制。通过对比传统工具,突出Mathcad在自然数学表达、实时单位换算和动态参数关联方面的独特优势,帮助电源工程师大幅提升设计效率。文章还提供了已验证的产品案例和实用模板,助力工程师快速掌握谐振参数优化技巧。

weixin_42548888的博客 546

模拟ic入门——设计一个带隙基准Bandgap(三)高阶温度补偿与启动电路设计

本节我们来介绍高阶温度补偿,以及一些启动电路的设计,附上一些经典的论文供大家学习

qq_64956710的博客 1万+

c++11 中的 move 与 forward

[update: 关于左值右值的另一点总结,请参看这篇] 一. move 关于 lvaue 和 rvalue,在 c++11 以前存在一个有趣的现象:T& 指向 lvalue (左传引用), const T& 既可以指向 lvalue 也可以指向 rvalue。但却没有一种引用类型,可以限制为只指向 rvalue。这乍看起来好像也不是很大的问题,但实际与看起来不一样,右值引用...

weixin_34302561的博客 292

机器视觉应用工程师职位深度解析与面试指南

广东奥普特科技招聘机器视觉应用工程师,要求大专以上理工科专业背景,熟悉C/C++或PLC编程,具备自动化设备调试经验。岗位职责包括视觉项目方案评估、系统安装调试、售后技术支持及异常处理,需接受外派出差。该职位面向专业对口的应届生或实习生,强调动手能力、沟通技巧和吃苦耐劳精神。机器视觉工程师需掌握图像处理算法、硬件配置等核心技术,在工业自动化领域具有良好发展前景。求职者应注重编程能力和实践经验的积累,以胜任这一技术密集型岗位。

郑伟强dev的专栏 431

Pytorch中关于forward函数的理解与用法

深入深度学习框架的代码,发现forward函数没有被显示调用但代码确重写了forward函数,于是好奇是不是python的魔术方法起的作用。

码农研究僧的博客 7545

【微电网优化】基于粒子群求解CHP机组、气网、电网、储热罐和电锅炉微电网优化模型附matlab代码

1 简介 我国风力发电近年发展迅速,装机容量已成为全球首位.随着风力发电在电力系统中的渗透率不断提高,我国多个地区(尤其是"三北"地区)已经面临着十分严峻的风电消纳问题,产生不容忽视的弃风问题.针对目前我国风电消纳存在的困难,本文提出粒子群优化CHP机组、气网、电网、储热罐和电锅炉微电网控制策略. 2 部分代码 Ppv=[0;0;0;0;0;0;9.86000000000000;19.0100000000000;33.1000000000000;45.0700000000000;64.7900000

qq_59747472的博客 672

一、DMSP/OLS、NPP/VIIRS等夜间灯光数据能源碳排放空间化理论介绍

利用DMSP/OLS、NPP/VIIRS等夜间灯光数据开展能源碳排放空间化之前,需要区分与利用夜间灯光数据GDP空间化,两者操作流程并无较大区别,只是GDP空间化选择夜间灯光指数种类有比较多包括总灯光指数、平均灯光指数、综合灯光指数等,但是能源碳排放过程中通常只选择总灯光指数,其次能源碳排放空间化可能对于某些省份工业相对没有那么发达的区域,构建模型时候拟合效果比较差,也就是R方低一些或者显著性差。针对上述拟合度低的情况诸多学者前辈从多个方面开展研究进行提升。

端木宛白的博客家园 4924

深入理解C++中的move和forward!

导语|在C++11标准之前,C++中默认的传值类型均为Copy语义,即:不论是指针类型还是值类型,都将会在进行函数调用时被完整的复制一份!对于非指针而言,开销及其巨大!因此在C++11以后,引入了右值和Move语义,极大地提高了效率。本文介绍了在此场景下两个常用的标准库函数:move和forward。一、特性背景(一)Copy语义简述C++中默认为Copy语义,因此...

QcloudCommunity的博客 5527

RK3568平台YOLOv11模型部署全流程实战:环境搭建、模型转换与性能优化解析

在AI边缘计算领域,瑞芯微RK3568芯片凭借其强大的NPU算力和丰富的接口资源,成为了众多开发者的首选平台。然而,瑞芯微官方文档虽然提供了YOLO11预训练模型的部署方案,但对于需要自定义数据集训练的开发者来说,从模型训练到板端部署的完整流程却缺乏详细指导。本文将带你走完从环境搭建、数据准备、模型训练到最终板端部署的完整技术路线,并分享实际开发中遇到的各种坑点和解决方案。让我们一起探索如何在RK3568平台上实现30FPS稳定推理的YOLO11目标检测应用!

LXY_LOVE36的博客 120

浅谈C++11中的move和forward

含义 move和forward都是C++11中引入的,它们是移动语义和完美转发实现的基石。 move:不能移动任何东西,它唯一的功能是将一个左值强制转化为右值引用,继而可以通过右值引用使用该值,以用于移动语义 从实现上讲,std::move基本等同于一个类型转换:static_cast<T&&>(lvalue) forward: 不转发任何东西,也是执行左值到右值的强制类型转换,只是仅在特定条件满足时才执行该转换 典型使用场景:某个函数模板取用了万能引用类型为形参,随

guotianqing的博客 2816

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C++11 move和forward实现原理

因此,在std::forward模板函数中,推断出_Ty的类型为int&&,std::remove_reference用int&& 进行实例化,std::remove_reference的type成员是int,在forward源码中有static_cast,则forward会返回右值引用类型。这时候就发现其实move也没干什么大事,参数是万能引用类型&&,因此经过引用折叠,调用处传入左值,则_Arg是左值引用T&,调用处传入右值,则_Arg是右值引用T&&

长期更新自学笔记 2326

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【C++】 C++中的move和forward的联系和区别

在 C++98/03 中,对象的传递和赋值通常需要进行。

qq_31638535的博客 1198

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

C++11 中的move和forward函数

它接受一个参数(通过通用引用,即模板类型参数的右值引用),并返回该参数的右值引用(或对于左值参数,在概念上返回一个左值引用,尽管实际上是通过返回右值引用来模拟的)。总之,std::move 和移动语义是C++中用于优化性能和资源管理的重要工具,通过允许对象在赋值或初始化时转移资源而非复制它们,它们可以减少不必要的资源复制并提高程序效率。但是,实际使用时,我们通常会通过std::forward_as_tuple或直接在模板函数中使用std::forward来利用C++的类型推导特性,使得代码更简洁。

1373

C++11 move和forward

1、概念介绍 最近刚好把它们俩梳理了一遍, 来写写move和forward为什么会出现, 他们能解决什么痛点. (1) 问题: 临时变量copy开销太大 (2) 引入: rvalue, lvalue, rvalue reference概念 (3) 方法: rvalue reference传临时变量, move语义避免copy (4) 优化: forward同时能处理rvalue/lvalue reference和const reference 2、两个C++的基础背景 2.1、..

xujianjun229的博客 391

C++中什么时候用move,什么时候用forward?

两者主要的区别: move的真实含义 一.move() 二.forworad<>()

weixin_42224577的博客 1461

C++11中std::move和std::forward到底干了啥

C++11中的右值引用的出现,在特定情况下减少了对象的拷贝,提升了C++程序的效率,伴随而来的 `std::move` 和 `std::forward` 也大量出现在程序代码中,但是这两个函数究竟干了啥呢?其实他们的本质都是转换函数,也就是完成左值和右值之间的转换,需要注意的是左值可以转换成右值,但是右值无法转换成左值...

AlbertS Home of Technology 6674

【C++】move-forward

微信搜索:编程笔记本。获取更多干货! 微信搜索:编程笔记本。获取更多干货! 对象移动与转发 文章目录对象移动与转发1. 移动1.1 右值引用1.2 标准库 move 函数1.3 理解 std::move2. 转发2.1 使用 std::forward 保持类信息 1. 移动 1.1 右值引用 C++11 新标准的一个很重要的特性是可以移动而非拷贝对象的能力。在很多情况下,程序中会发生对象拷贝,但在一些情况下,对象拷贝后就立即被销毁了。在这种情况下,移动而非拷贝对象会有大幅度性能提升。 标准库容器、stri

qq_42247231的博客 534

C++ move和forward

在这两篇文件的基础之上; 优快云 优快云 vector右值引用的push_back方法 引用重叠: 左值引用+右值引用=左值引用 右值引用+右值引用=右值引用

LIJIWEI0611的博客 1080

move std 函数 示例_C++11朝码夕解: move和forward

move和forward虽然是8年前C++提出的新东西, 但要搞懂还是得费一些精力.网上有挺多相关材料, 但即使是stackoverflow, 对move和forward的讲解, 要么抠底层抠到入土, 要么东拉西扯, 都是隔靴搔痒.最近刚好把它们俩梳理了一遍, 来写写move和forward为什么会出现, 他们能解决什么痛点.太长不看细节: TL;DR:(1) 问题: 临时变量copy开销太大(2...

weixin_39893274的博客 127

c++ move的变量还能使用吗_C++11朝码夕解: move和forward

move和forward虽然是8年前C++提出的新东西, 但要搞懂还是得费一些精力.网上有挺多相关材料, 但即使是stackoverflow, 对move和forward的讲解, 要么抠底层抠到入土, 要么东拉西扯, 都是隔靴搔痒.最近刚好把它们俩梳理了一遍, 来写写move和forward为什么会出现, 他们能解决什么痛点.太长不看细节: TL;DR:(1) 问题: 临时变量copy开销太大(2...

weixin_29973493的博客 1571

c++ move和forward

右值引用、移动语义和完美转发可以参考这篇文章 https://www.jianshu.com/p/d19fc8447eaa 一.move /usr/include/c++/7/bits/move.h template<typename _Tp> constexpr typename std::remove_reference<_Tp>::type&am...

kh815的博客 341
上一篇: C++【左值与右值】
下一篇: 如何在VisualStudio上创建开发64位工程详解
pstrunner
博客等级 码龄19年 50粉丝 52原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值