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

哪些网站首页做的好网站建设上

哪些网站首页做的好,网站建设上,小说网站wordpress,网站内做二级目录#x1f31f;#x1f31f;作者主页#xff1a;ephemerals__ #x1f31f;#x1f31f;所属专栏#xff1a;C 目录 前言 一、列表初始化 1. 大括号初始化 2. initializer_list 二、右值引用和移动语义 1. 左值和右值 2. 左值引用和右值引用 引用延长生命周期 左… 作者主页ephemerals__ 所属专栏C 目录 前言 一、列表初始化 1. 大括号初始化 2. initializer_list 二、右值引用和移动语义 1. 左值和右值 2. 左值引用和右值引用 引用延长生命周期 左值引用和右值引用的参数匹配原则 右值引用的适用场景 引用折叠与万能引用 完美转发 三、类的新默认成员函数 1. 移动构造函数 2. 移动赋值函数 四、lambda表达式 1. 捕捉列表 显式捕捉 隐式捕捉 混合捕捉 捕捉列表的其他要点 2. lambda表达式的适用场景 总结 前言 c11 标准的发布为 c 带来了革命性的变化引入了许多强大的新特性使代码更简洁、高效且现代化。这些特性不仅提升了开发效率还优化了性能是现代 c 编程的重要基石。本篇文章我们将重点探讨 c11 的几个核心改进列表初始化、右值引用和移动语义、类的新默认成员函数以及lambda表达式。 一、列表初始化 1. 大括号初始化 在c98中允许数组和结构体使用大括号初始化例如 #include iostream using namespace std;struct STU {int a;double b; };int main() {int arr[5] { 1,2,3,4,5 };STU s { 3,5.5 };return 0; } 而在c11之后统一了初始化方式“ 一切对象 ”均可以用大括号进行初始化也叫做列表初始化十分方便。举例 int a { 2 }; const STU rs { 3,5.5 }; //引用临时对象 对于自定义类型使用大括号初始化本质是一种隐式类型转换会产生临时对象不过很多编译器会将其进行优化为直接构造对象。 注意使用大括号初始化时赋值符号可以省略。 int a{ 1 }; STU s{ 2,3.1 }; const STU rs{ 3,5.5 }; c11的大括号初始化方式也在某些场景下带来了许多便利例如调用容器接口操作多参数类型构造的对象时 #include iostream #include vector #include string using namespace std;int main() {vectorpairstring, int v;//v.push_back(pairstring, int(hello, 1)); //传统的方式--构造匿名对象v.push_back({ hello, 1 }); //使用大括号构造pair十分方便return 0; } 2. initializer_list 虽然刚才提到的大括号初始化已经十分方便但是对于容器的多元素初始化仍旧有些麻烦。所以c11引入了一个新容器 -- initializer_list初始化列表/初始化器并在STL各种容器中增加了有它支持的构造函数、拷贝构造函数和赋值重载。代码示例 #include iostream #include vector #include list #include map using namespace std;int main() {vectorint v { 1,2,3,4,5 };listdouble l { 3.1,5.2,4.8 };mapstring, int m { {hello, 1}, {hehe, 3} };return 0; } 这里赋值使用的大括号及其内部元素即是initializer_list。它也有自己的定义方式 //两种方式均可 auto il1 { 1,2,3,4,5 }; initializer_listint il2 { 1,2,3,4,5 }; initializer_list的本质是一个数组其元素存放在栈区当中它的迭代器是原生指针内部有两个迭代器分别指向其开始位置和结束位置。我们使用它对容器进行构造或赋值时是构造了一个initializer_list的对象然后调用容器的相应函数去遍历initializer_list一个个地构造。 二、右值引用和移动语义 在某些情况下使用传统的左值引用并不能提高效率 vectorstring v; v.push_back(hello); //“hello”是临时对象不能直接进行引用 而在c11当中引入了一种新的引用--右值引用。 1. 左值和右值 左值一般是一个持久存在的表达式 有明确内存地址可以进行取地址操作。左值既可以放在赋值号左边也可以放在赋值号右边。 右值指那些临时性的即将被销毁的以及常量表达式没有明确的内存地址不能进行取地址操作。右值不能放在赋值号左边。 2. 左值引用和右值引用 顾名思义左值引用是给左值取别名右值引用是给右值取别名。举个例子 #include iostream using namespace std;int main() {int a 0;int r1 a; //左值引用int r2 1; //右值引用return 0; } 左值引用不能直接引用右值需要加上const右值引用不能直接引用左值需要将左值使用move函数包装起来move将左值转化为右值引用。示例 #include iostream using namespace std;int main() {const int r1 1; //左值引用引用右值int a 0;//右值引用引用左值int r2 (int)a; //强转int r3 move(a); //使用move函数return 0; } 需要注意这里的 r2 和 r3 虽然是右值引用但是 r2 和 r3 本身还是左值是可以取到地址的。 在语法层面上看左值引用和右值引用都是给变量或常量取别名不会开辟内存。但是从底层实现的角度上讲左值引用和右值引用本质都是用指针实现的与指针并没有什么区别。我们在学习语法的时候语法所表达的意义与底层可能是背离的尽量不要混到一起容易陷入迷途。 引用延长生命周期 const左值引用和右值引用都可以延长临时对象的生命周期直至引用的生命周期结束但const左值引用所引用的对象不可被修改而通过右值引用可以修改所引用的临时对象因为右值引用本身是左值。 示例 #include iostream using namespace std;int main() {const int r1 1 3;r1; // 报错表达式必须是可修改的左值int r2 1 3;r2; // 可以修改return 0; } 左值引用和右值引用的参数匹配原则 在c98当中被const修饰的左值引用形参既可以接收左值也可以接收右值。而在c11当中由于引入了右值引用所以当同时存在两个形参分别为右值引用和const的左值引用的重载函数时如果我们传入左值那么会优先调用const左值引用的重载函数如果传入右值则会优先调用右值引用版本的重载函数。 代码示例 #include iostream using namespace std;//const左值引用版本 void func(const int x) {cout 调用左值引用 endl; }//右值引用版本 void func(int x) {cout 调用右值引用 endl; }int main() {int a 0;func(a); // 传入左值func(1); // 传入右值func(move(a)); // 传入右值return 0; } 注意在右值引用版本的重载函数中参数x的性质是左值之前已经提到所以如果要将x作为参数传入一个形参是右值引用的函数中需要使用move或强转为右值引用类型。 那么右值引用存在的意义是什么呢实际上右值引用的核心价值在于支持移动语义主要体现在移动构造和移动赋值这两个新默认成员函数中。我们具体分析一下。 右值引用的适用场景 虽然说左值引用可以在对象的传参和返回时减少拷贝提高效率。但如果对象在函数体内部创建其离开函数体时就会销毁。如果要传值返回或强行传引用返回就会发生拷贝/出现野引用。 此时右值引用的作用就体现出来了右值引用可以接收即将被销毁的对象再以左值的形式在对象销毁之前配合移动构造或移动赋值将对象的资源直接移走避免拷贝从而提效。 string类的移动构造和移动赋值实现示例 //移动构造 //接收一个右值通过右值引用转化为左值 string(string s) {swap(s);//使用swap直接掠夺即将销毁的对象的资源 }//移动赋值 string operator(string s) {swap(s);return *this; } 有了移动构造函数体内部定义的对象传值返回后由于返回值是即将销毁的对象会被移动构造给临时对象临时对象再移动构造/移动赋值给当前接收对象这样就完成了两次资源转移在没有编译器优化的情况下也避免拷贝。 传参时如果传入临时对象也会通过移动构造直接将资源进行移动免去了对象拷贝时的时间消耗。 注意如果我们将左值经过move转化传给移动构造那么左值的资源会被掠夺。 string s2 move(s1); // 此时s1的资源被掠夺 引用折叠与万能引用 c不能直接定义引用的引用但我们可以使用typedef的方式间接定义引用的引用称之为引用折叠。示例 #include iostream using namespace std;typedef int lr; typedef int rr;int main() {int a 0;lr r1 a;lr r2 a;rr r3 a;rr r4 1;return 0; }; 这样就会产生四种甚至更多的引用类型显得十分杂乱。为了使这种语法兼具实用性和简洁性c规定引用折叠的规则是右值引用的右值引用表示右值引用其余均表示左值引用。所以这里的r1,r2,r3都是左值引用r4是右值引用。 引用折叠的机制与模板相结合产生了“万能引用” templateclass T void func(T x) {//... } 当给func函数传入左值时T会被实例化为左值引用类型与右值引用折叠成左值引用当传入右值时T会被实例化为右值类型与“”结合形成右值引用。 万能引用使得模板函数在接受参数时既能处理左值也能处理右值使代码更具灵活性和可扩展性。 完美转发 如果我们给万能引用函数传入右值由于右值引用变量本身是左值所以如果用这个右值引用在内部嵌套调用其他函数就无法保持参数的属性传入的其实为左值从而无法达到预期效果。为此C提供了一个函数forward完美转发保持属性。 示例 #include iostream #include utility using namespace std;void func2(int x) {cout 左值版本 endl; }void func2(int x) {cout 右值版本 endl; }templateclass T void func1(T x) {func2(x); //预期是调用func2的右值引用版本但x是左值func2(forwardT(x));// 使用完美转发传入右值 }int main() {func1(1);return 0; } 运行结果 这里我们想要将func1的右值引用形参x传给func2并调用func2的右值引用版本但是x作为右值引用语法规定其本身是左值类型所以直接传入就会调用func2的左值引用版本。完美转发保持了x的右值属性方便我们正确调用函数。 完美转发的本质是一个函数模板它基于模板参数T的类型决定是否使用move将左值转化为右值从而保持原始参数的值属性确保不会因为出现左值引用而产生不必要的临时对象拷贝避免降低效率。 三、类的新默认成员函数 c11在原有的六个默认成员函数的基础上新增了两个函数移动构造函数和移动赋值函数。之前已经提到了它们面对临时对象拷贝时的优势这里我们再系统介绍一下这两个函数的特点。 1. 移动构造函数 移动构造函数是构造函数的一个重载类似于拷贝构造函数主要用于提高临时对象拷贝时的性能。它的特性如下 1. 移动构造函数的第一个参数必须是该类类型的右值引用如果还有其他参数要求这些参数要有缺省值。 2. 如果我们没有显式实现移动构造函数也没有显式实现析构函数、拷贝构造和赋值重载那么编译器会默认生成一个移动构造函数。这个自动生成的移动构造函数进行移动构造时如果遇到内置类型成员会逐个拷贝遇到自定义类型的成员则会调用该成员的移动构造。如果该成员没有移动构造则会调用其拷贝构造。 //移动构造 string(string s) {swap(s); } 2. 移动赋值函数 与赋值重载类似移动赋值对已经存在的对象的赋值并且会将对方的资源移走。它的特性 1. 移动赋值必须重载为成员函数且其第一个参数必须是该类类型的右值引用一般情况下将返回值类型设置为该类类型的左值引用减少拷贝提高效率。 2. 如果我们没有显式实现移动赋值函数也没有显式实现析构函数、拷贝构造和赋值重载那么编译器会默认生成一个移动赋值函数。这个自动生成的移动赋值函数进行移动赋值时如果遇到内置类型成员会逐个拷贝遇到自定义类型的成员则会调用该成员的移动赋值。如果该成员没有移动赋值则会调用其赋值重载。 //移动赋值 string operator(string s) {swap(s);return *this; } 注意对于内部需要动态申请资源要进行资源深拷贝的类移动构造和移动赋值才有意义因为移动构造和移动赋值的本质是“窃取”临时对象的资源而不是像拷贝构造或赋值重载那样去完成资源的深拷贝这样才能提高效率。 四、lambda表达式 lambda表达式与仿函数类似是c11新引入的一种匿名函数对象。与普通函数不同的是它可以定义在函数体内部。 它的语法格式如下 [捕捉列表](参数列表)-返回值类型{函数体} 示例 #include iostream using namespace std;int main() {//简单的lambda表达式auto f [](int x, int y)-int {return x y; };//调用cout f(1, 2) endl;return 0; } 注意lambda表达式的类型在语法层面是不具体的所以我们一般用auto或者模板参数定义的对象类型去接收lambda表达式。 这里使用 f 接收lambda表达式以后我们就可以像调用函数一样调用 f 并且进行传参。 在定义lambda表达式时有如下规则需要我们遵守 1. 捕捉列表的“[ ]”不能省略。 2. lambda表达式的参数为空时参数列表包括“( )”可以省略。 3. 返回值类型包括“-”可以省略。 4. 若返回值类型已写那么就算没有参数参数列表的“( )”也不能省略。 5. 函数体的“{ }”不能省略。 lambda表达式中的参数列表、返回值类型与函数体都很好理解与普通函数的含义相同但是这里的捕捉列表是什么呢 1. 捕捉列表 就像函数一样lambda表达式的函数体只能使用其对应参数列表中的变量无法使用到外部变量。而捕捉列表可以让我们在lambda表达式的函数体当中使用外层变量。 捕捉一共分为三种分别是显式捕捉、隐式捕捉和混合捕捉。 显式捕捉 显式捕捉就是在捕捉列表当中显式写明要在函数体中使用的变量。示例 #include iostream using namespace std;int main() {int a 1;int b 3;auto f [a](int x){//return a b x; // 报错b不能使用return a x; //捕捉列表中写明了a可以使用a};cout f(1) endl;return 0; } 当然如果我们要在函数体内部修改变量a的值是不允许的因为这里的a是传值捕捉。如果要修改a的值那么需要传引用捕捉 auto f [a](int x) // a前面加一个 隐式捕捉 相比显式捕捉隐式捕捉就显得十分便利它的机制是函数体内部使用了哪些变量就捕捉哪些变量。 隐式捕捉也分为传值捕捉和传引用捕捉 auto f1 [] {}; // 隐式的传值捕捉 auto f2 [] {}; // 隐式的传引用捕捉 使用了隐式捕捉之后我们就可以在函数体内部任意使用外部的变量编译器会根据我们使用的变量自动捕捉它们。 混合捕捉 如果我们需要在隐式捕捉的基础上确保其中某些值可以被修改或不能被修改那么就可以使用混合捕捉。示例如下 auto f1 [, a] {}; // 其他变量使用传值捕捉a使用传引用捕捉 auto f2 [, a] {}; // 其他变量使用传引用捕捉a使用传值捕捉 注意混合捕捉当中捕捉列表的第一个位置必须是“”或“”如果混合捕捉的隐式部分使用了传值捕捉那么其他特定变量就不能设置为传值捕捉没必要传引用捕捉同上。 捕捉列表的其他要点 1. 全局变量和静态变量不能捕捉也没必要捕捉可以直接使用。 2. 对于传值捕捉其本质是将外层数据进行拷贝并加上const进行修饰所以函数体内部没办法修改它。如果想要修改捕捉的值而不影响外部可以在参数列表之后返回值类型之前加上关键字mutable。示例 #include iostream using namespace std;int main() {int a 0;auto f []() mutable -int //这里的返回值类型可以省略{a; //可以修改a且不影响外部的areturn a;};return 0; } 注意加上关键字mutable后那么就算没有参数参数列表的“( )”也不能省略。 2. lambda表达式的适用场景 在lambda表达式出现之前可调用对象只有函数指针和仿函数两种但它们定义起来都比较麻烦。lambda和它们的作用类似功能也十分强大在某些场景下编码也会更加方便因为它是匿名函数对象。 示例 sort(a.begin(), a.end(), [](const A a1, const A a2){//直接定义排序规则}); 除此之外lambda在线程中定义线程的执行函数逻辑、智能指针的删除器定义等场景中也十分适用。 总结 本篇文章我们主要学习了c11的部分新特性列表初始化、右值引用、类的新默认成员函数和lambda表达式。通过剖析引用折叠、完美转发等底层机制lambda的多种捕捉方式与适用场景希望能帮助大家在资源管理、代码简洁性及性能提升之间找到平衡。之后博主会和大家分享c11其他的新特性如可变参数模板、包装器、智能指针等。如果你觉得博主讲的还不错就请留下一个小小的赞在走哦感谢大家的支持❤❤❤
http://www.pierceye.com/news/390878/

相关文章:

  • 网站建设服务器环境配置郑州网站建设企业名录
  • e福州官方网站wordpress注册目录
  • 国际外贸网络交易平台网页seo搜索引擎优化
  • 做网做网站建设网站建设图片怎么切
  • 国外数码印花图案设计网站36kr wordpress
  • 上海网站建设设计公司zencart 网站入侵
  • 阜蒙县自治区建设学校网站汉中市住建局建设厅网站官网
  • windows 2008 iis怎么搭建网站手机网站模板建站
  • 优设网官网首页seo教程搜索引擎优化
  • 做问卷给钱的网站页面设计结课总结
  • 洛阳集团网站建设wordpress 深度优化
  • python做网站缺点湛江市建网站
  • 济南网站建设(选聚搜网络)在线购物网站建设
  • 珠海专业做网站公司昆明搜索引擎推广
  • 阿里云 建设网站怎么样百度推广一级代理商名单
  • 湛江网站制作网站吉林省四平市网站建设
  • 酒店网站建设公司推广方法有哪些
  • 网站建设免备案免费空间wordpress在线教育主题购买
  • 网站后台验证码不显示成都市建设工程施工安监站网站
  • 榆林网站优化做图的网站
  • 在微信中做网站淄博 网站seo优化
  • 黑龙江省建设协会网站首页怎么用word做网站
  • 企业网站网站建设价格wordpress阶梯插件
  • 企业品牌建设方案范文roseonly企业网站优化
  • 电影资源采集网站咋做在百度上怎么建立网站吗
  • 好的企业网站设计方案中小企业网站建设 论文
  • 毕设网站建设论文网站开发合同履约
  • 织梦贷款网站源码备案过的网站换域名
  • 南宁网站seo顾问广州正规的免费建站
  • 温州教育网站建设建网站 陕西牛人网络科技