前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++ 新特性学习(七) — 右值引用

C++ 新特性学习(七) — 右值引用

作者头像
owent
发布2018-08-01 16:59:03
6150
发布2018-08-01 16:59:03
举报
文章被收录于专栏:owent

C++在效率上有个硬伤。我们知道C#和Java对于类传递都是以引用的方式,而C++默认都是传值。在传值过程中就经常会进行复制构造,这完全没必要而且浪费CPU,为了解决这种问题,于是乎C++11 增加了一个新的非常数引用(reference)类型,称为右值引用(R-value reference)。我就专门看了一下关于右值引用的东西。 右值引用在GCC 4.3之后开始支持,VS 2010(VC 10.0)已经支持,再前一点的VC版本没试过所以不知道。 右值引用的申明标记为T &&,主要用于处理临时变量,比如函数返回的变量(暂时想不出其他例子,忽略返回值优化吧,(命名)返回值优化参见http://efnetcpp.org/wiki/Return_value_optimization,再说返回值优化能力有限是吧,比要求如单返回语句、不能使用异常等等),避免复制构造。同时在析构的时候就不会析构这个临时变量,从而提升效率。 上代码:

代码语言:javascript
复制
class foo {
public:
    int m;
    foo(){ puts("directly"); }
    foo(const foo&){ puts("copy"); }
    foo(int i){ puts("int"); m = i; }
};

foo foo_func1(int flag)
{
    if(flag == 1)
        return foo();
    if(flag == 2)
        return foo(1);

    // 此处返回值优化就是个渣渣
    foo retv;
    return retv;
}

foo&& foo_func2(int flag)
{
    if(flag == 1)
        return foo();
    if(flag == 2)
        return foo(1);

    // 返回值优化就这么跪了
    foo retv;
    return std::move(retv);
}

foo rr1 = foo_func1(0); // 1
foo&& rr2 = foo_func2(0); // 2

对于1,如果没有右值引用,首先rr1调用foo的复制构造函数,然后析构返回的fs对象。 对于2,有右值引用,返回的foo对象直接传给rr2,少了一步复制构造和释放foo对象的操作。

基本原理就是这样,经实测,右值引用在字符串操作上可以带来近30%的效率提升。

另外,介绍两个和右值引用相关的函数

std::move 提取右值引用

代码语言:javascript
复制
template<class _Ty> inline
    typename _Ty &&
        move(_Ty&& _Arg) _NOEXCEPT
    {   // forward _Arg as movable
        return ((typename _Ty &&)_Arg);
    }

这个函数用于显示告诉编译器,我要拿到右值,很多情况下函数有重载的时候,会优先使用传值的形式,使用这个函数可以指定取回右值引用,这样可以阻止临时对象的析构和复制构造

std:: forward 引用参数转发

代码语言:javascript
复制
template<class _Ty> inline
_Ty&& forward(typename remove_reference<_Ty>::type& _Arg) { // forward an lvalue
    return (static_cast<_Ty&&>(_Arg));
}

template<class _Ty> inline
_Ty&& forward(typename remove_reference<_Ty>::type&& _Arg) _NOEXCEPT {  // forward anything
    static_assert(!is_lvalue_reference<_Ty>::value, "bad forward call");
    return (static_cast<_Ty&&>(_Arg));
}

// 其中移除引用的代码如下
// TEMPLATE remove_reference
template<class _Ty>
struct remove_reference { // remove reference
    typedef _Ty type;
};

template<class _Ty>
struct remove_reference<_Ty&> { // remove reference
    typedef _Ty type;
};

template<class _Ty>
struct remove_reference<_Ty&&> { // remove rvalue reference
    typedef _Ty type;
};

很多情况下,我们会直使用模板进行操作,当_Ty为左值引用类型时,u将被转换为_Ty类型的左值,否则u将被转换为_Ty类型右值,据说是拿来做保留左右值属性的完美转发的。

所谓完美转发(详见提案N1385),就是模板函数接收到什么类型,就转发给其调用的函数什么类型,详见:http://blog.csdn.net/pongba/article/details/1697636

漫漫长路,下一站,原子操作和多进程编程

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2012-05-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • std::move 提取右值引用
  • std:: forward 引用参数转发
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档