zoukankan      html  css  js  c++  java
  • C++14的右值引用能解决什么问题呢?

    现在有这么几个结构体:

    typedef struct _info_head{
    	u_int src_ip;
    	u_int dest_ip;
    	u_int src_port; 
    	u_int dest_port;
    }info_head;
    
    typedef struct _pkt_info{
    	u_long sec;
    	u_long u_sec;
    	u_int pkt_size;
    	u_int pld_size;
    } pkt_info;
    
    typedef struct _pkt{
    	info_head head;
    	pkt_info info;
    } pkt;
    

      虽然这几个结构体都是由基本类型构成的,而且也不涉及动态内存管理,但是体积确实是有一点的。其中info_head是16字节,pkt_info是24个字节,那么一个pkt就是40个字节啦。这还只是在32位的机器上的情况。

      之后我们又遇到了一个这样的类,这个类使用list容器,存储了多个pkt类型的变量。

    class pkt_list{
    public:
    	static list< pkt > head_to_pkt;
    
    public:
    	static int append(const info_head &, const pkt_info &);
    };
    

      下面就来实现一下append()函数吧

    int pkt_list::append(const info_head &head, const pkt_info &info){
    	pkt tmp;
    	tmp.head = head;
    	tmp.info = info;
    	
    	head_to_pkt.push_back(tmp);
    
    	return 1;
    }
    

      由于pkt只包含基本类型,所以直接用就好啦,不用new,也不用担心内存管理的问题。

      这里我们看到了第一个问题,要想把一组info_head和pkt_info类型的变量合并成一个pkt类型的变量,就必须重新组建一个pkt类型的变量。就是说,内存中已经有了16B的info_head和24B的pkt_info之后,但是还要再使用40B去存储和前边一对变量值完全相同的一个pkt类型的变量。虽然有浪费内存的嫌疑,但这个是避免不了的,因为我们没法保证之前的那两个16B和24B的东西就挨在一起。所以其实也不能算是浪费。

      但是接下来又有一个问题,就是把这个pkt类型的变量,搬进list<pkt>里时,内存又做了一次拷贝。因为tmp在append函数结束后就消失了,那么理所当然的,想要在list<pkt> head_to_pkt里留住这个变量的信息,就只好再拷贝一份了。

      那么这样算下来,我们已经用了120B的内存来保存同一段数据了。这样确实是一个很浪费的举动。但是在C++14出现之前,我们无能为力。

      C++14中提出了右值引用的概念,也叫move语义。具体怎么个意义就不说了,直接说效果,那就是可以省下40B的开销。但这是咋做到的呢?很简单,就是直接把第二次的那40B直接移入容器中就可以了,而不是再拷贝复制一次。这么说来,list<T>::push_back(T&);就应该又另一个更高效的版本了,那就是list<T>::push_back(T&&);。总的来说,STL有得重写了。

      接下来,为了使用第二个版本的push_back函数的重载,我们必须在参数列表里写上作为右值的无名变量,但是如果已经使用了一个寄存器变量tmp,那么这40B的开销是无论如何也省不下来的,因此tmp已经有了名字,就不再是右值了。而要想得到pkt类型的无名变量,就要重新为pkt写一个构造函数了。全部改完之后,大概是这个样子的。

    class pkt{
    public:
    	pkt(){}
    	pkt(const info_head &h, const pkt_info i):
    		head(h), info(i){}
    
    	info_head head;
    	pkt_info info;
    };
    
    ...
    
    int pkt_list::append(const info_head &head, const pkt_info &info){
    	head_to_pkt.push_back( pkt( head, info ) );
    	//With move semantics version being used, it works.  
    
    	return 1;
    }
    

      OK。就总结这么多。

  • 相关阅读:
    Https 原理与工作流程及证书链校验
    ORA-12516, TNSlistener could not find available handler with matching protocol stack
    报表框架整合记录20210422
    Spring MVC
    JasperReports with Spring
    Spring Boot + Jasper Report + MySQL Database Example
    Spring Boot + Jasper Report Example
    JasperReports with Spring Boot
    Spring 4 Jasper Report integration example with mysql database in eclipse
    JasperReports Java Spring project
  • 原文地址:https://www.cnblogs.com/superpig0501/p/4093975.html
Copyright © 2011-2022 走看看