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

免费软件下载公众号单页应用seo如何解决

免费软件下载公众号,单页应用seo如何解决,政府网站建设 宽屏,wordpress调用菜单的代码目录 1、引言 2、值类别及相关概念 3、左值、右值 4、左值引用、右值引用 5、移动语义 5.1、为什么需要移动语义 5.2、移动语义定义 5.3、转移构造函数 5.4、转移赋值函数 6、标准库函数 std::move 7、完美转发 std::forward VC常用功能开发汇总(专栏文章…

目录

1、引言

2、值类别及相关概念

3、左值、右值

4、左值引用、右值引用

5、移动语义

5.1、为什么需要移动语义

5.2、移动语义定义

5.3、转移构造函数

5.4、转移赋值函数

6、标准库函数 std::move

7、完美转发 std::forward


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章正在更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html       C++11新特性很重要,作为C++开发人员很有必要去学习,不仅笔试面试时会涉及到,开源代码中会大规模的使用。以很多视频会议及直播软件都在使用的开源WebRTC项目为例,WebRTC代码中大篇幅地使用了C++11及以上的新特性,要读懂其源码,必须要了解这些C++的新特性。所以,接下来一段时间我将结合工作实践,给大家详细讲解一下C++11的新特性,以供借鉴或参考。

1、引言

       C++11引入了对象移动的概念,是一种移动而非拷贝对象的能力,移动对象可以有效地提高程序的性能。

       为了支持移动操作,C++11引入了一种新的引用类型 - 右值引用(rvalue references)。所谓右值引用,是必须要绑定到右值的引用,通过&&操作符获得右值引用。今天就来详细讲讲左值、左值引用、右值、右值引用相关的内容。

2、值类别及相关概念

       在C++11中,值类别主要分为左值、左值引用、右值与右值引用。左值引用是绑定到左值的应用,右值引用则是绑定到右值的引用。当右值引用T&&出现在模板函数的参数中,T是模板类型,T&&则是万能引用。万能引用可以接收左值参数,也可以接收右值参数。然后在推导函数参数类型时,可能会发生引用折叠。还会涉及到标准库函数std::move和std::forward。

3、左值、右值

       在C语言中,我们常常会提起左值(lvalue)、右值(rvalue)这样的称呼。一个最为典型的判别方法就是,在赋值表达式中,出现在等号左边的就是“左值”,而在等号右边的,则称为“右值”。如:

int b = 1;
int c = 2;
int a = a + b;

在这个赋值表达式中,a就是一个左值,而b + c则是一个右值。

       不过C++中还有一个被广泛认同的说法,那就是可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值。那么这个加法赋值表达式中,&a是允许的操作,但&(b + c)这样的操作则不会通过编译。因此a是一个左值,(b + c)是一个右值。相对于左值,右值表示字面常量、表达式、函数的非引用返回值等。

       这里总结一下,什么是左值:

1)能被赋值(充分非必要条件),左值不一定能被赋值,比如const变量,智能在初始化时赋初值,后续不能赋值
2)能取址(充分非必要条件),左值不一定能取址,比如C语言中的register变量:register int i= 3,C++11已经取消了对register的支持,编译时会忽略。再比如C语言中的位域变量是不能取址的:
struct St{ int m:3;} St st; st.m = 3; 指定int型成员m占3个字节。
3)可以初始化左值引用(必要不充分条件),左值可以初始化左值引用,比如:int m = 3; int& n = m;,右值不能初始化左值引用,比如:const int& m = 3; 因为3是右值,不能初始化左值引用,所以编译会报错。
4)字面量属于纯右值,比如1,2,3等立即数就属于字面量,注意,常量字符串“xyz”是左值,可以对该字符串进行取址,即&"xyz"。
5)将亡值可以偷其中的资源。函数的返回值,则是纯右值,返回右值引用,比如std::move函数。

4、左值引用、右值引用

       左值引用是对一个左值进行引用的类型,右值引用则是对一个右值进行引用的类型。左值引用和右值引用都是属于引用类型。无论是声明一个左值引用还是右值引用,都必须立即进行初始化。而其原因可以理解为是引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名。

        左值引用是具名变量值的别名,而右值引用则是不具名(匿名)变量的别名。

        左值引用示例:

int &a = 2;       // 左值引用绑定到右值,编译失败, err
int b = 2;        // 非常量左值
const int &c = b; // 常量左值引用绑定到非常量左值,编译通过, ok
const int d = 2;  // 常量左值
const int &e = c; // 常量左值引用绑定到常量左值,编译通过, ok
const int &b = 2; // 常量左值引用绑定到右值,编程通过, ok

“const 类型 &”为 “万能”的引用类型,它可以接受非常量左值、常量左值、右值对其进行初始化;

       右值引用,使用&&表示:

int && r1 = 22;
int x = 5;
int y = 8;
int && r2 = x + y;
T && a = ReturnRvalue();

       通常情况下,右值引用是不能够绑定到任何的左值的:

int c;
int && d = c; //err

       下面看一个测试示例:

void process_value(int & i) //参数为左值引用
{cout << "LValue processed: " << i << endl;
}void process_value(int && i) //参数为右值引用
{cout << "RValue processed: " << i << endl;
}int main()
{int a = 0;process_value(a); //LValue processed: 0process_value(1); //RValue processed: 1return 0;
}

5、移动语义

5.1、为什么需要移动语义

       右值引用是用来支持转移语义的。转移语义可以将资源 ( 堆,系统对象等 ) 从一个对象转移到另一个对象,这样能够减少不必要的临时对象的创建、拷贝以及销毁,能够大幅度提高 C++ 应用程序的性能。临时对象的维护 ( 创建和销毁 ) 对性能有严重影响。

       转移语义是和拷贝语义相对的,可以类比文件的剪切与拷贝,当我们将文件从一个目录拷贝到另一个目录时,速度比剪切慢很多。通过转移语义,临时对象中的资源能够转移其它的对象里。

5.2、移动语义定义

       在现有的 C++ 机制中,我们可以定义拷贝构造函数和赋值函数。要实现转移语义,需要定义转移构造函数,还可以定义转移赋值操作符。对于右值的拷贝和赋值会调用转移构造函数和转移赋值操作符。

       如果转移构造函数和转移拷贝操作符没有定义,那么就遵循现有的机制,拷贝构造函数和赋值操作符会被调用。普通的函数和操作符也可以利用右值引用操作符实现转移语义。

5.3、转移构造函数

       先来看个转移构造函数的实例:

class MyString
{
public:MyString(const char *tmp = "abc"){//普通构造函数len = strlen(tmp);  //长度str = new char[len+1]; //堆区申请空间strcpy(str, tmp); //拷贝内容cout << "普通构造函数 str = " << str << endl;}MyString(const MyString &tmp){//拷贝构造函数len = tmp.len;str = new char[len + 1];strcpy(str, tmp.str);cout << "拷贝构造函数 tmp.str = " << tmp.str << endl;}//移动构造函数//参数是非const的右值引用MyString(MyString && t){str = t.str; //拷贝地址,没有重新申请内存len = t.len;//原来指针置空t.str = NULL;cout << "移动构造函数" << endl;}MyString &operator= (const MyString &tmp){//赋值运算符重载函数if(&tmp == this){return *this;}//先释放原来的内存len = 0;delete []str;//重新申请内容len = tmp.len;str = new char[len + 1];strcpy(str, tmp.str);cout << "赋值运算符重载函数 tmp.str = " << tmp.str << endl;return *this;}~MyString(){//析构函数cout << "析构函数: ";if(str != NULL){cout << "已操作delete, str =  " << str;delete []str;str = NULL;len = 0;}cout << endl;}private:char *str = NULL;int len = 0;
};MyString func() //返回普通对象,不是引用
{MyString obj("mike");return obj;
}int main()
{MyString &&tmp = func(); //右值引用接收return 0;
}


和拷贝构造函数类似,有几点需要注意:

1)参数(右值)的符号必须是右值引用符号,即“&&”。
2)参数(右值)不可以是常量,因为我们需要修改右值。
3)参数(右值)的资源链接和标记必须修改,否则,右值的析构函数就会释放资源,转移到新对象的资源也就无效了。

       有了右值引用和转移语义,我们在设计和实现类时,对于需要动态申请大量资源的类,应该设计转移构造函数和转移赋值函数,以提高应用程序的效率。 

5.4、转移赋值函数

         直接看转移赋值函数的实例:

class MyString
{
public:MyString(const char *tmp = "abc"){//普通构造函数len = strlen(tmp);  //长度str = new char[len+1]; //堆区申请空间strcpy(str, tmp); //拷贝内容cout << "普通构造函数 str = " << str << endl;}MyString(const MyString &tmp){//拷贝构造函数len = tmp.len;str = new char[len + 1];strcpy(str, tmp.str);cout << "拷贝构造函数 tmp.str = " << tmp.str << endl;}//移动构造函数//参数是非const的右值引用MyString(MyString && t){str = t.str; //拷贝地址,没有重新申请内存len = t.len;//原来指针置空t.str = NULL;cout << "移动构造函数" << endl;}MyString &operator= (const MyString &tmp){//赋值运算符重载函数if(&tmp == this){return *this;}//先释放原来的内存len = 0;delete []str;//重新申请内容len = tmp.len;str = new char[len + 1];strcpy(str, tmp.str);cout << "赋值运算符重载函数 tmp.str = " << tmp.str << endl;return *this;}//移动赋值函数//参数为非const的右值引用MyString &operator=(MyString &&tmp){if(&tmp == this){return *this;}//先释放原来的内存len = 0;delete []str;//无需重新申请堆区空间len = tmp.len;str = tmp.str; //地址赋值tmp.str = NULL;cout << "移动赋值函数\n";return *this;}~MyString(){//析构函数cout << "析构函数: ";if(str != NULL){cout << "已操作delete, str =  " << str;delete []str;str = NULL;len = 0;}cout << endl;}private:char *str = NULL;int len = 0;
};MyString func() //返回普通对象,不是引用
{MyString obj("mike");return obj;
}int main()
{MyString tmp("abc"); //实例化一个对象tmp = func();return 0;
}

6、标准库函数 std::move

       编译器只对右值引用才能调用转移构造函数和转移赋值函数,而所有命名对象都只能是左值引用,如果已知一个命名对象不再被使用而想对它调用转移构造函数和转移赋值函数,也就是把一个左值引用当做右值引用来使用,怎么做呢?标准库提供了函数 std::move,这个函数以非常简单的方式将左值引用转换为右值引用。

int a;
int &&r1 = a;              // 编译失败
int &&r2 = std::move(a);      // 编译通过

7、完美转发 std::forward

        完美转发适用于这样的场景:需要将一组参数原封不动的传递给另一个函数。“原封不动”不仅仅是参数的值不变,在 C++ 中,除了参数值之外,还有一下两组属性:左值/右值和 const/non-const。完美转发就是在参数传递过程中,所有这些属性和参数值都不能改变,同时,而不产生额外的开销,就好像转发者不存在一样。在泛型函数中,这样的需求非常普遍。

       下面举例说明:

#include <iostream>
using namespace std;template <typename T> void process_value(T & val)
{cout << "T &" << endl;
}template <typename T> void process_value(const T & val)
{cout << "const T &" << endl;
}
//函数 forward_value 是一个泛型函数,它将一个参数传递给另一个函数 process_value
template <typename T> void forward_value(const T& val)
{process_value(val);
}template <typename T> void forward_value(T& val)
{process_value(val);
}int main()
{int a = 0;const int &b = 1;//函数 forward_value 为每一个参数必须重载两种类型,T& 和 const T&forward_value(a); // T&forward_value(b); // const T &forward_value(2); // const T&return 0;
}

        对于一个参数就要重载两次,也就是函数重载的次数和参数的个数是一个正比的关系。这个函数的定义次数对于程序员来说,是非常低效的。

        那C++11是如何解决完美转发的问题的呢?实际上,C++11是通过引入一条所谓“引用折叠”(reference collapsing)的新语言规则,并结合新的模板推导规则来完成完美转发。

typedef const int T;
typedef T & TR;
TR &v = 1; //在C++11中,一旦出现了这样的表达式,就会发生引用折叠,即将复杂的未知表达式折叠为已知的简单表达式

        C++11中的引用折叠规则:

TR的类型定义

声明v的类型

v的实际类型

T &

TR

T &

T &

TR &

T &

T &

TR &&

T &

T &&

TR

T &&

T &&

TR &

T &

T &&

TR &&

T &&

注意,一旦定义中出现了左值引用,引用折叠总是优先将其折叠为左值引用。       C++11中,std::forward可以保存参数的左值或右值特性:

#include <iostream>
using namespace std;template <typename T> void process_value(T & val)
{cout << "T &" << endl;
}template <typename T> void process_value(T && val)
{cout << "T &&" << endl;
}template <typename T> void process_value(const T & val)
{cout << "const T &" << endl;
}template <typename T> void process_value(const T && val)
{cout << "const T &&" << endl;
}//函数 forward_value 是一个泛型函数,它将一个参数传递给另一个函数 process_value
template <typename T> void forward_value(T && val) //参数为右值引用
{process_value( std::forward<T>(val) );//C++11中,std::forward可以保存参数的左值或右值特性
}int main()
{int a = 0;const int &b = 1;forward_value(a); // T &forward_value(b); // const T &forward_value(2); // T &&forward_value( std::move(b) ); // const T &&return 0;
}

文章转载自:
http://uncreate.pwmm.cn
http://modulate.pwmm.cn
http://expiscate.pwmm.cn
http://semireligious.pwmm.cn
http://streamy.pwmm.cn
http://dorado.pwmm.cn
http://gelatinize.pwmm.cn
http://skylit.pwmm.cn
http://newsagent.pwmm.cn
http://nonnutritive.pwmm.cn
http://safekeep.pwmm.cn
http://counter.pwmm.cn
http://mydriatic.pwmm.cn
http://disassociation.pwmm.cn
http://savorless.pwmm.cn
http://meet.pwmm.cn
http://legionaire.pwmm.cn
http://frowsty.pwmm.cn
http://russianise.pwmm.cn
http://kiplingesque.pwmm.cn
http://vop.pwmm.cn
http://puseyism.pwmm.cn
http://ferrophosphorous.pwmm.cn
http://spoiler.pwmm.cn
http://shy.pwmm.cn
http://tabor.pwmm.cn
http://yeggman.pwmm.cn
http://motility.pwmm.cn
http://sepsis.pwmm.cn
http://hydrometer.pwmm.cn
http://pot.pwmm.cn
http://cheerily.pwmm.cn
http://mbps.pwmm.cn
http://columbium.pwmm.cn
http://jovial.pwmm.cn
http://staminiferous.pwmm.cn
http://disputable.pwmm.cn
http://tiddledywinks.pwmm.cn
http://bedpost.pwmm.cn
http://hypogastrium.pwmm.cn
http://grouse.pwmm.cn
http://ducktail.pwmm.cn
http://talismanic.pwmm.cn
http://galvanography.pwmm.cn
http://erratic.pwmm.cn
http://birdcage.pwmm.cn
http://denizen.pwmm.cn
http://cave.pwmm.cn
http://tarada.pwmm.cn
http://cowpea.pwmm.cn
http://gravenstein.pwmm.cn
http://essentic.pwmm.cn
http://executer.pwmm.cn
http://euphausiid.pwmm.cn
http://falchion.pwmm.cn
http://apophthegm.pwmm.cn
http://halbert.pwmm.cn
http://puzzlepated.pwmm.cn
http://insecticidal.pwmm.cn
http://denaturalize.pwmm.cn
http://midsummer.pwmm.cn
http://copse.pwmm.cn
http://songkok.pwmm.cn
http://pulverization.pwmm.cn
http://ovulation.pwmm.cn
http://synergid.pwmm.cn
http://dissimilation.pwmm.cn
http://pemba.pwmm.cn
http://colleger.pwmm.cn
http://fermion.pwmm.cn
http://posturize.pwmm.cn
http://whippoorwill.pwmm.cn
http://clubwoman.pwmm.cn
http://misogamist.pwmm.cn
http://polychloroprene.pwmm.cn
http://serigraphy.pwmm.cn
http://grassfinch.pwmm.cn
http://subset.pwmm.cn
http://chlordane.pwmm.cn
http://asepticism.pwmm.cn
http://dc.pwmm.cn
http://nationalist.pwmm.cn
http://vicinity.pwmm.cn
http://behalf.pwmm.cn
http://replace.pwmm.cn
http://anthophagy.pwmm.cn
http://cotswolds.pwmm.cn
http://sweatily.pwmm.cn
http://torpid.pwmm.cn
http://bibitory.pwmm.cn
http://fickleness.pwmm.cn
http://commuterland.pwmm.cn
http://stylostatistics.pwmm.cn
http://blare.pwmm.cn
http://citrullin.pwmm.cn
http://telemarketing.pwmm.cn
http://fiche.pwmm.cn
http://radon.pwmm.cn
http://mercer.pwmm.cn
http://legateship.pwmm.cn
http://www.dt0577.cn/news/81851.html

相关文章:

  • 网站建设项目必应bing搜索引擎
  • 乐都网站建设企业seddog站长之家
  • 泰安网络网站软件推广是什么工作
  • seo整站优化+WordPress百度关键词推广条件
  • WordPress博客整站带数据seo搜索引擎
  • 下载应用的appseo基础培训
  • 阳江做网站苏州网站
  • 白日梦怎么做的网站百度关键词seo外包
  • 网站栏目策划 有思想的新闻企业如何做网站
  • 做性事的视频网站种子搜索神器 bt 下载
  • 网站开发区网站推广多少钱一年
  • 克隆网站后怎么做宁波网站制作设计
  • 青岛公司做网站的价格网页设计培训
  • 小网站建设公司排名今日百度搜索风云榜
  • 培训网站建设学校seo软件推荐
  • 建做一个av网站seo培训公司
  • 手机微信网页版登录入口seo网站推广免费
  • 网站开发进度设计与阶段目标微帮推广平台怎么加入
  • 商务网站的类型一共有几大类百度今日排行榜
  • 南昌网站建设大全网站代运营价格
  • 经典的响应式布局网站张家界seo
  • 商城展示网站建设百度西安
  • 动态网站开发 PHP一键制作网站
  • 网络营销推广的方式和特点推推蛙seo顾问
  • 建俄语网站网站构建的基本流程
  • 可做生物试卷的网站在线网站建设平台
  • wordpress外贸商城主题东莞seo排名扣费
  • 网站meta 优化建议网站建站
  • 凡科互动游戏作弊软件搜索引擎优化的方法与技巧
  • 注册一个个人网站网易搜索引擎