C++ 0x 之移动语义和传导模板实现原理

文 / 李博(光宇广贞)

       《C++ 0x 之左值与右值》文中提到 std::forward()std::move()。本文开头对之补充一句:

    在操作函数返回值或函数参数时,匿名左值仍然为左值,左值可以具名;匿名右值仍然为右值,右值一旦具名成功,立即转变为左值。

       举一个例子。使用 std::move() 方法向 Outer 传递右值后,使用 std::forward() 保证调用右值重载,而直接访问参数 t 的调用绑定到了左值重载。见下图:

c1

       因此,操作右值引用不能直接操作其变量名,否则将使右值引用具名,从而转为左值引用。操作右值引用必须使用 std::move()、std::forword() 等方法。将两个方法的实体展开如下:

5

       这两个 identityRemove_Reference 是干嘛用的?若不要它们,直接用 T&& 做为 forward 里 arg 的类型或 move 里返回类型呢?

       不行。首先说 forward 方法。重新看如下代码:

       template < typename T > void Outer ( T&& t )
       {
              Inner ( std::forward<T> ( t ) );
       }

       在《C++ 0x 之左值与右值》文中提到,我们使用 forward 的目的是保证参数的左右值性和只读性的准确传导。若不使用 identity 而只使用 T&& 的话,调用 std::forward<T>(t) 仍然没有问题;而当调用 std::forward(t),即不指明模板参数类型时,T&& 将由 t 推导,问题便来了。注意到 t 在传参数时,是点名调用,使 t 具名,故而无论原来 t 是左值还是右值,此刻都将视为左值,从而 T 被推导为左值引用,且 T&& 归化为左值引用,于是 forward 方法以左值引用类型接收参数 t,并以左值作为其返回类型。如是便违背了 forward 的本意。

       而使用 identity 后,type 被指定为 T。注意这里,“::”算符就像一面墙,挡住了类型推导看见其左侧。因此,编译器不会认为 arg 参数是需要类型推导的,是被 identity::type 指定类型的(当然也强制使用 forward 时要注明模板参数,否则将无从推导)。这就保证了 forward 总是以右值引用类型接收参数 t。前文已经提到右值引用类型参数可以保留实参的一切信息。如是保证了 forward 的本意的实现。

       最后,move 方法里面的 Remove_Reference 就好解释了。模板将根据 arg 推导类型,若 arg 是 const Type& 型,则 T 推导为 const Type& 型,而后代入特化模板,使 type 为 const Type,从而返回类型为 const Type&& 型。若 arg 是右值类型,则 type 也将归化为右值引用型。总之,Remove_Reference 模板类保证返回类型为右值引用。


       所属分类:C++

       参考:

       C++ 0x 之 Lambda:贤妻与娇娃,你娶谁当老婆?听 FP 如何点化 C++

       从 C++ 模板元编程生产质数看 F# 函数式编程思想

       人类最伟大的王安石时代,自古至今乃至不可预见的未来

       天生是兵家——一代神将“蒋方震”

       汉族姓氏与基因——为何有“两个汉族”?同姓是否同源?随父随母、生男生女是否一样?

       缅甸攻打果敢汉人与中印边界对峙的关系——东段麦克马洪线!

       限次连续若干同色球概率算法

       Vista 高级扫雷 105 秒到 135 秒各记录截图

       做为中国人,以下“历史片断”绝对颠覆你的想像!

       王夫人向贾母挑战

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值