当前位置: 首页 > news >正文

在哪个网站上可以找兼职做/郑州做网站推广哪家好

在哪个网站上可以找兼职做,郑州做网站推广哪家好,郴州新网最新招聘信息,蒙古网站群建设C11 增加了一个新的类型,称为右值引用(R-value reference),标记为 T &&。在介绍右值引用类型之前先要了解什么是左值和右值。左值是指表达式结束后依然存在的持久对象,右值是指表达式结束时就不再存在的临时对…

       C++11 增加了一个新的类型,称为右值引用(R-value reference),标记为 T &&。在介绍右值引用类型之前先要了解什么是左值和右值。左值是指表达式结束后依然存在的持久对象,右值是指表达式结束时就不再存在的临时对象。一个区分左值与右值的便捷方法是:看能不能对表达式取地址,如果能,则为左值,否则为右值 。所有的具名变量或对象都是左值,而右值不具名。

       在 C++11 中,右值由两个概念构成,一个是将亡值(xvalue, expiring value),另一个则是纯右值(prvalue, PureRvalue),比如,非引用返回的临时变量、运算表达式产生的临时变量、原始字面量和 lambda 表达式等都是纯右值。而将亡值是 C++11 新增的、与右值引用相关的表达式,比如,将要被移动的对象、 T&& 函数返回值、 std::move 返回值和转换为 T&&的类型的转换函数的返回值。

      C++11 中所有的值必属于左值、将亡值、纯右值三者之一 ,将亡值和纯右值都属于右值。区分表达式的左右值属性有一个简便方法:若可对表达式用 & 符取址,则为左值,否则为右值。

      右值引用就是对一个右值进行引用的类型。因为右值不具名,所以我们只能通过引用的方式找到它。

      无论声明左值引用还是右值引用都必须立即进行初始化,因为引用类型本身并不拥有所绑定对象的内存,只是该对象的一个别名。通过右值引用的声明,该右值又“重获新生”,其生命周期与右值引用类型变量的生命周期一样,只要该变量还活着,该右值临时量将会一直存活下去。

class A_2
{
public:A_2() :m_ptr(new int(0)){}~A_2(){delete m_ptr;}private:int* m_ptr;
};A_2 Get(bool flag)
{A_2 a;A_2 b;if (flag)return a;elsereturn b;
}int right_value_ref2()
{A_2 a = Get(false);  //运行报错return 0;
}

       在上面的代码中,默认构造函数是浅拷贝,a和b会指向同一指针m_ptr,在析构函数会导致重复删除该指针。

       正确的做法是提供深拷贝的拷贝构造函数。

A_2(const A_2& a):m_ptr(new int(*a.m_ptr)) //深拷贝
{std::cout << "copy construct" << std::endl;
}
//这样就可以保证拷贝构造时的安全性,但有时这种拷贝构造却是不必要的,不人上面代码中的拷贝构造就是不必要的。上面代码中的Get函数会返回临时变量,
//然后通过这个临时变量拷贝构造一个新的对象b,临时变量在拷贝构造完成之后就销毁了,如果堆内存很大,那么,这个拷贝构造的代价会很大,带来了额外的性能损耗。
//有没有办法避免临时对象的拷贝构造呢?答案是肯定的。看下面的代码:
class A_2
{
public:A_2() :m_ptr(new int(0)){std::cout << "construct" << std::endl;}A_2(const A_2& a):m_ptr(new int(*a.m_ptr)) //深拷贝{std::cout << "copy construct" << std::endl;}A_2(A_2&& a) :m_ptr(a.m_ptr){// 这一步很关键,真正实现资源拥有权的转移,如果去掉这一步,a.m_ptr在移动构造函数结束时候执行析构函数// 会将我们偷来的内存析构掉。a.m_ptr会变成悬垂指针。如果我们对指针解引用,就会发生严重的运行错误a.m_ptr = nullptr; std::cout << "move construct:" << std::endl;}~A_2(){std::cout << "destruct" << std::endl;delete m_ptr;}private:int* m_ptr;
};A_2 Get(bool flag)
{A_2 a;A_2 b;if (flag)return a;elsereturn b;
}int right_value_ref2()
{A_2 a = Get(false);return 0;
}

 

       上面的代码中没有了拷贝构造,取而代之的是移动构造(Move Construct)。从移动构造函数的实现可以看到,它的参数是一个右值引用类型的参数A&&,这里没有深拷贝,只有浅拷贝,这样就避免了临时对象的深拷贝,提供了性能。这里的A&&用来根据参数是左值还是右值来建立分支,如果是临时值,则会选择移动构造函数。移动构造函数只是将临时对象的资源做了浅拷贝,不需要对其进行深拷贝,从而避免了额外的拷贝,提高性能。这也就是所谓的移动语义(move 语义),右值引用的一个重要目的是用来支持移动语义的。值得注意的是移动构造里面将a.m_ptr置为nullptr(注释写得很清楚),此时delete不会对nullptr做出任何操作。

       移动语义可以将资源(堆、系统对象等)通过浅拷贝方式从一个对象转移到另一个对象,这样能减少不必要的临时对象的创建、拷贝以及销毁,可以大幅度提高C++应用程序的性能,消除临时对象的维护(创建和销毁)对性能的影响

 

再看一个简单的例子,代码如下:

struct Element
{Element(){}// 右值版本的拷贝构造函数Element(Element&& other) : m_children(std::move(other.m_children)){}Element(const Element& other) : m_children(other.m_children){}
private:vector<ptree> m_children;
};

 

这个 Element 类提供了一个右值版本的构造函数。这个右值版本的构造函数的一个典型

应用场景如下:

void Test()
{Element t1 = Init();vector<Element> v;v.push_back(t1);v.push_back(std::move(t1));
}

 

       先构造了一个临时对象 t1,这个对象中一个存放了很多 Element 对象,数量可能很多,如果直接将这个 t1 用 push_back 插入到 vector 中,没有右值版本的构造函数时,会引起大量的拷贝,这种拷贝会造成额外的严重的性能损耗。通过定义右值版本的构造函数以及

std::move(t1) 就可以避免这种额外的拷贝,从而大幅提高性能。

       有了右值引用和移动语义,在设计和实现类时,对于需要动态申请大量资源的类,应该设计右值引用的拷贝构造函数和赋值函数,以提高应用程序的效率。需要注意的是,我们一般在提供右值引用的构造函数的同时,也会提供常量左值引用的拷贝构造函数,以保证移动不成还可以使用拷贝构造。

      这里也要注意对 move 语义的误解, move 只是转移了资源的控制权,本质上是将左值强制转换为右值引用,以用于 move 语义,避免含有资源的对象发生无谓的拷贝。 move 对于拥有形如对内存、文件句柄等资源的成员的对象有效。如果是一些基本类型,比如 int 和char[10] 数组等,如果使用 move,仍然会发生拷贝(因为没有对应的移动构造函数),所以说move 对于含资源的对象来说更有意义。

      还要注意的是,右值引用不能绑定左值:int a;  int &&c = a;   这样是不行的。

 

另附一段右值引用性能测试的代码:


#define  MAX_TIMES 1000class A {
public:A(const char *pstr) {m_data = (pstr != 0 ? strcpy(new char[strlen(pstr) + 1], pstr) : 0);}A(const A &a) {m_data = (a.m_data != 0 ? strcpy(new char[strlen(a.m_data) + 1], a.m_data) : 0);}A &operator =(const A &a) {if (this != &a) {delete[] m_data;m_data = (a.m_data != 0 ? strcpy(new char[strlen(a.m_data) + 1], a.m_data) : 0);}return *this;}A(A &&a) : m_data(a.m_data) {a.m_data = 0;}A & operator = (A &&a) {if (this != &a) {m_data = a.m_data;a.m_data = 0;}return *this;}~A() { delete[] m_data; }
private:char * m_data;
};//移动语义实现
void swap1(A& a, A& b)
{A tmp(move(a));a = (move(b));b = move(tmp);
}// 普通交换
void swap2(A& a, A& b)
{A tmp = a;a = b;b = tmp;
}int main()
{A a("123"), b("456");clock_t start, finish, start1, finish1;double totaltime;start = clock();for (int i = 0; i < MAX_TIMES; ++i){swap1(a, b);}finish = clock();totaltime = (double)(finish - start) / CLOCKS_PER_SEC;cout << "MAX_TIMES =" << MAX_TIMES << "\n右值引用的运行时间为" << totaltime << "秒!" << endl;start1 = clock();for (int i = 0; i < MAX_TIMES; ++i){swap2(a, b);}finish1 = clock();totaltime = (double)(finish1 - start1) / CLOCKS_PER_SEC;cout << "MAX_TIMES =" << MAX_TIMES << "\n普通的运行时间为" << totaltime << "秒!" << endl;cin.get();return 0;
}

 

测试结果:

10000次以下时几乎没有差别,这里不列出;

 

通过大量的测试表明,右值引用内比普通的构造性能确实要高,我这边测试大约是15倍的样子。

http://www.lbrq.cn/news/1358335.html

相关文章:

  • 济宁网站建设多少钱/上海好的网络推广公司
  • 有哪些网站可以做设计挣钱/福建seo学校
  • 做黄金的经常看什么网站/seo培训一对一
  • 旅游网站如何做/千万不要做手游推广员
  • 苏州知名网站建设公司/搜索推广出价多少合适
  • 广州市专业做商城网站/直播营销
  • 专做hiphop的网站/搜索词
  • 做百度网站的公司哪家好/网络营销与管理
  • 北京手机网站建设/互联网推广运营是做什么的
  • 网站建设方案书格式/域名注册服务网站
  • 发优惠券网站怎么做/百度文库登录入口
  • 福田做网站的/b2b网站有哪些平台
  • 网页网站动作效果做的比较棒/国外服务器免费ip地址
  • 网站公司是做什么的/免费的黄冈网站有哪些
  • 做办公设备网站/商丘seo教程
  • 字形分析网站/百度推广培训
  • 禁用软件app大全/福州关键词排名优化
  • 纯ajax网站如何做seo/百度小说官网
  • 自己做游戏网站学什么/今天的新闻
  • 多语种网站制作/学it什么培训机构好
  • 千图app的优势/长沙seo网络优化
  • 个体工商户能够做经营性网站吗/站长工具seo排名
  • 住房和城市建设部网站/百度seo排名优化软件
  • 榆林电商网站建设/上海网络推广培训机构
  • 个人网站建设方法和过程/暴疯团队seo课程
  • 盐城做网站企业/长春网站开发公司
  • 江苏做网站的公司/网络优化工具app手机版
  • 城乡建设部网站安全员证书查询/什么叫营销
  • 公司网站备案需要每年做吗/如何制作简单的网页链接
  • 做婚庆网站的功能定位/在百度怎么创建自己的网站
  • TCP的拥塞控制
  • AI+UI:如何用智能算法提升设计效率10倍?
  • Docker Desktop
  • 前端实现Excel文件的在线预览效果
  • C++高频知识点(十四)
  • FreeRTOS源码分析四:时钟中断处理响应流程