C++11的新特性

        C++11是由C++标准委员会指定的语言规范。相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140 个新特性,以及对C++03标准中约600个缺陷的修正,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅 功能更强大,而且能提升程序员的开发效率。

列表初始化{ }

C++11扩大了{ }的适用范围,使得{ }可以用于所有内置类型和用户自定义类型。

具体例子:

#include<iostream>
#include <vector>
#define NUM 2
class Base
{
public:Base(int left, int right):_left(left),_right(right){}private:int _left;int _right;
};
int main()
{int array[2] = { 1, 2 };std::vector<int> v = { 1, 2, 3 };Base b = { 1, 2 };return 0;
}

变量类型推导auto

应用场景:变量类型太长或者创建变量不清楚类型时。

具体例子:

#include <iostream>
#include <unordered_map>
int main()
{std::unordered_map<std::string, std::string> hash = { {"apple", "苹果"}};std::unordered_map<std::string, std::string>::iterator it = hash.begin();auto cur = it;return 0;
}

注意事项:

1、auto类型不可做函数形参,auto声明的变量必须由编译器在编译时期推导而得。auto推导的类型都是已经被初始化的。

2、当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

3、用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&。

decltype类型推导

应用场景:解决需要根据表达式运行完成之后所得结果的类型推导问题。

具体例子:

#include <iostream>
int Func()
{return -1;
}
int main()
{int a = 10;int b = 20;decltype(a + b) c;decltype(Func()) funcType;std::cout << typeid(funcType).name() << std::endl;//intreturn 0;
}

范围for

C++11中提供的一种遍历容器的方法

具体例子:

#include <iostream>
#include <vector>
#include <list>
int main()
{std::list<int> _list = { 1,2,3 };std::vector<int> _v = { 1,2,3 };for (int e : _list)std::cout << e << std::endl;for (int e : _v)std::cout << e << std::endl;return 0;
}

        可以结合auto来进行类型推导,也可以在类型后加&,表示以引用的方式来依此提取右边容器内的元素。

final与override

final和override在C++的多态中使用。

1、final:修饰虚函数,表示该虚函数不能被重写

2、override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写则编译报错。

具体使用:

class Car
{
public:virtual void Drive() final {}
};
class Benz : public Car
{
public:virtual void Drive() {cout << "Benz-舒适" << endl;}
};class Car
{
public:virtual void Drive(){}
};
class Benz : public Car {
public:virtual void Drive() override {cout << "Benz-舒适" << endl;}
};

默认成员函数控制

默认成员函数控制又包括显示缺省函数删除默认函数。

        在C++中对于空类编译器会生成一些默认的成员函数,比如:构造函数、拷贝构造函数、运算符重载、析构 函数和&和const&的重载、移动构造、移动拷贝构造等函数。如果在类中显式定义了,编译器将不会重新生成默认版本。有时候这样的规则可能被忘记,最常见的是声明了带参数的构造函数,必要时则需要定义不带 参数的版本以实例化无参的对象。而且有时编译器会生成,有时又不生成,容易造成混乱,于是C++11让程序员可以控制是否需要编译器生成。

显示缺省函数

C++11中,可以在函数声明或定义时加上 =default 显式的指示编译器生成该函数的默认版本,用=default 修饰的函数称为显式缺省函数。

具体用法:

class Base
{
public:Base(int left, int right):_left(left), _right(right){}Base() = default;
private:int _left;int _right;
};

删除默认函数

如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且不给定义,这样只要其他 人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即可,该语法指示编译器不生成对 应函数的默认版本,称 =delete 修饰的函数为删除函数。

具体使用:

class Base
{
public:Base(int left, int right):_left(left), _right(right){}Base() = default;Base(const Base&) = delete;Base& operator=(const Base&) = delete;
private:int _left;int _right;
};

右值引用

为了提高程序运行效率,C++11引入右值引用,顾名思义,右值引用只能引用右值。形似int&&

左值与右值

1、 普通类型的变量,因为有名字,可以取地址,都认为是左值。

2.、const修饰的常量,不可修改,只读类型的,理论应该按照右值对待,但因为其可以取地址(如果只是 const类型常量的定义,编译器不给其开辟空间,如果对该常量取地址时,编译器才为其开辟空间), C++11认为其是左值。

3、如果表达式的运行结果是一个临时变量或者临时对象,认为是右值。

4、 如果表达式运行结果或单个变量是一个引用则认为是左值。

左值引用和右值引用

左值引用只能引用左值,但const左值引用既可以引用左值,也可以引用右值。

右值引用一般只能引用右值,但可以引用move后的左值。

具体例子:

int main()
{int a = 10;int& pa = a;int& pb = 10;//报错,左值引用无法引用右值const int& ppa = a;const int& ppb = 10;int&& pa2 = 10;int&& pb2 = a;//报错,右值引用无法引用左值int&& ppa2 = std::move(a);return 0;
}

引入右值引用的具体原因

本质是为了减少拷贝次数,提高效率。例如一个类中的拷贝构造和操作符重载,传值返回时,必须拷贝构造一个临时对象,再通过返回的临时对象来构造接受结果的对象。

看下面一段代码:

class Base
{
public:Base(int left, int right):_left(left), _right(right){}Base operator+(const Base& b){Base tmp (_left + b._left, _right + b._right);return tmp;}
private:int _left;int _right;
};
int main()
{Base a(1, 2);Base b(3, 4);Base c(a + b);return 0;
}

        在operator+中:tmp在按照值返回时,必须创建一个临时对象,临时对象创建好之后,tmp就被销毁了,最后使用返回的临时对象构造c,c构造好之后,临时对象就被销毁了。仔细观察会发现:tmp和所形成临时对象,以及c,每个对象创建后,都有自己独立的空间,而空间中存放内容也都相同,相当于创建了三个内容完 全相同的对象,对于空间是一种浪费,程序的效率也会降低,而且临时对象确实作用不是很大。

移动语义

        C++11提出了移动语义,将一个对象中的资源转移到另一个对象中。依然是上面的代码,通过移动语义,会将tmp返回时构造的临时对象识别为”将亡值“,C++11认为临时对象为右值,将返回对象的资源直接转移给该临时对象,而再构造c时,又会调用移动语义,直接将返回的临时对象资源转移给对象c。

注意:

1、 移动构造函数的参数不能设置成const类型的右值引用,因为资源无法转移而导致移动语义失效。

2.、在C++11中,编译器会为类默认生成一个移动构造,该移动构造为浅拷贝,因此当类中涉及到资源管理时,用户必须显式定义自己的移动构造。

        当需要用右值引用引用一个左值时,可以通过move函数将左值转化为右值。C++11中std::move()函数位于 头文件中,唯一的功能就是将一个左值强制转化为右值引用,然后实现移动语义。被转化的左值,其生命周期并没有随着左值的转化而改变,即std::move转化的左值变量value不会被销毁,但会变的无效。

完美转发

        完美转发是指在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另外一个函数。所谓完美:函数模板在向其他函数传递自身形参时,如果相应实参是左值,它就应该被转发为左值;如果相 应实参是右值,它就应该被转发为右值。

       万能引用,既可以接收左值,也可以接收右值,但万能引用虽然都能接收,但是统一都退化为左值,所以要通过完美转发来保持实参原有的属性。

具体例子:

#include <iostream>
void Fun(int& x) 
{std::cout << "left_value ref" << std::endl;
}
void Fun(int&& x) 
{std::cout << "right_value ref" << std::endl;
}
template<typename T>
void PerfectForward(T&& t) 
{ Fun(std::forward<T>(t));
}
int main()
{int a = 10;PerfectForward(a);PerfectForward(std::move(a));return 0;
}

移动语义具体例子:

#include <iostream>
class Base
{
public:Base(Base&& b):_left(std::move(b._left)),_right(std::move(b._right)){}Base operator=(Base&& b){_left = b._left;_right = b._right;}
private:int _left;int _right;
};

lambda表达式

本质是一种匿名函数。

应用场景:使用algorithm中的sort时,对自定义类型对象进行排序,需要给出对应的比较规则,往往都是通过仿函数来实现,但每出现一个类别,就要定义一个类,写一个用于比较的仿函数,比较繁琐,而lambda表达式可以很好的解决这个问题。

具体例子:

sort(goods, goods + sizeof(goods) / sizeof(goods[0]), [](const Goods& l, const Goods& r)->bool{return l._price < r._price;});

lambda表达式语法

[capture-list] (parameters) mutable -> return-type { statement }

1、[ ]捕捉列表,编译器根据[ ]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。

包括

父作用域:指包含lambda函数的语句块

[ = ]:对父作用域进行传值捕捉

[ & ]:对父作用域进行传引用捕捉

[ val ]:对val变量进行传值捕捉

[ &val ]:对val变量进行传引用捕捉

[ this ]:对当前this指针进行传值捕捉

2、( )参数列表,和普通函数的参数列表相同,可以不传参数。

3、mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。

4、->return-type,表示该lambda表达式最终返回值的类型,可以省略。

5、{ }函数体,除了可以使用其参数外,还可以使用所有捕获到的变量。

        lambda表达式实际上可以理解为无名函数,该函数无法直接调用,如果想要直接调用,可借助auto将其赋值给一个变量。

注意:. lambda表达式之间不能相互赋值,即使看起来类型相同。

        实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,即:如果定义了一 个lambda表达式,编译器会自动生成一个类,在该类中重载了operator()。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/818916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构 -- 数组

本篇文章主要是对数组的实操&#xff0c;所以对数组的概念不在赘述&#xff0c;了解更多数组相关可参照链接 Java数组的概念及使用-CSDN博客 1、DynamicArray类 package com.hh.algorithm.array;import java.util.Arrays; import java.util.Iterator; import java.util.functi…

记录--病理切片图像处理

简介 数字病理切片&#xff0c;也称为全幻灯片成像&#xff08;Whole Slide Imaging&#xff0c;WSI&#xff09;或数字切片扫描&#xff0c;是将传统的玻片病理切片通过高分辨率扫描仪转换为数字图像的技术。这种技术对病理学领域具有革命性的意义&#xff0c;因为它允许病理…

【linux】如何写一个launch文件

编写一个ROS&#xff08;Robot Operating System&#xff09;的launch文件是为了方便地启动一组相关的节点&#xff08;nodes&#xff09;、参数服务器&#xff08;parameter server&#xff09;参数、消息发布者/订阅者&#xff08;publishers/subscribers&#xff09;、服务&…

深入浅出 -- 系统架构之Spring、SpringBoot、SpringCloud的区别

首先我们做技术&#xff0c;尤其是java开发人员&#xff0c;应该对Spring、SpringBoot、SpringCloud 三个家伙一点不陌生。 结合发展史Spring出现的最早&#xff0c;后面为了可以让开发人员偷懒&#xff0c;简化配置&#xff0c;就是约定犹于配置或者说大于&#xff0c;进而出…

每日OJ题_BFS解决最短路③_力扣127. 单词接龙

目录 ③力扣127. 单词接龙 解析代码 ③力扣127. 单词接龙 127. 单词接龙 难度 困难 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk&#xff1a; 每一对相邻的单词只差一个字母。…

互联网元搜索引擎SearXNG

最近有个很火的项目叫 FreeAskInternet&#xff0c;其工作原理是&#xff1a; 第一步、用户提出问题第二步、用 SearXNG&#xff08;本地运行&#xff09;在多个搜索引擎上进行搜索第三步、将搜索结果传入 LLM 生成答案 所有进程都在本地运行&#xff0c;适用于需要快速获取信…

Python数据分析与应用 |第4章 使用pandas进行数据预处理 (实训)

表1-1healthcare-dataset-stroke.xlsx 部分中风患者的基础信息和体检数据 编号性别高血压是否结婚工作类型居住类型体重指数吸烟史中风9046男否是私人城市36.6以前吸烟是51676女否是私营企业农村N/A从不吸烟是31112男否是私人农村32.5从不吸烟是60182女否是私人城市34.4抽烟是…

【LAMMPS学习】八、基础知识(3.2)使用chunks计算系统属性

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

蓝桥杯 — —灵能传输

灵能传输 友情链接&#xff1a;灵能传输 题目&#xff1a; 输入样例&#xff1a; 3 3 5 -2 3 4 0 0 0 0 3 1 2 3输出样例&#xff1a; 3 0 3思路&#xff1a; 题目大意&#xff1a;给出一个数组&#xff0c;每次选择数组中的一个数&#xff08;要求不能是第一个数与最后一个…

若依下整合多个Redis

提前总结&#xff0c;因此项目已多处使用Redis1 故此我创建的Redis工厂只添加了Redis2并不影响Redis1。但如若还有Redis3、4、5可按照下述方法继续往Redis工厂里添加 下述代码添加到 RedisConfig import org.springframework.beans.factory.annotation.Autowired; import org…

大数据几种任务调度工具

文章目录 一、DolphinScheduler概述和部署1、DolphinScheduler简介1.1 概述1.2 核心架构 2、DolphinScheduler部署模式2.1 概述2.2 单机模式2.3 伪集群模式2.4 集群模式 3、DolphinScheduler集群模式部署3.1 集群规划与准备3.2 下载与配置部署脚本3.3 初始化数据库3.4 一键部署…

Fast DDS环境搭建

目录 Docker环境Fast DDS构建运行运行原有demo编译运行 本文主要记录Fast DDS docker环境搭建和examples代码运行 Docker环境 Fast DDS的docker环境可以直接在官网下载&#xff0c;如果自己要重新做一个&#xff0c;首先需要从Docker Hub上下载系统的docker镜像&#xff0c;由…

【LAMMPS学习】八、基础知识(3.1)LAMMPS 的输出

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

maven引入外部jar包

将jar包放入文件夹lib包中 pom文件 <dependency><groupId>com.jyx</groupId><artifactId>Spring-xxl</artifactId><version>1.0-SNAPSHOT</version><scope>system</scope><systemPath>${project.basedir}/lib/Spr…

Android gdb调试

Android gdb调试 前置条件&#xff1a; 1.Linux环境&#xff0c;比如Ubutun 2.python工具&#xff1a;建议2,7&#xff0c; 安装命令 sudo apt-get install libpython2.7 3.Android完整codebase 4.开发板 操作步骤&#xff1a; adb root adb remount adb shell #4027为进程id g…

电商技术揭秘二十四:无人仓储与自动化技术

相关系列文章 电商技术揭秘一&#xff1a;电商架构设计与核心技术 电商技术揭秘二&#xff1a;电商平台推荐系统的实现与优化 电商技术揭秘三&#xff1a;电商平台的支付与结算系统 电商技术揭秘四&#xff1a;电商平台的物流管理系统 电商技术揭秘五&#xff1a;电商平台…

华媒舍:7种方式,打造出旅游媒体套餐

现如今&#xff0c;伴随着旅游业发展与繁荣&#xff0c;更多旅游业发展从业人员越来越重视产品营销品牌基本建设&#xff0c;希望可以将自己的度假旅游产品和服务营销推广给更多的潜在用户。而建立一个优秀的旅游业发展媒体套餐内容品牌是吸引目标客户的重要步骤。下面我们就详…

Golang | Leetcode Golang题解之第30题串联所有单词的子串

题目&#xff1a; 题解&#xff1a; func findSubstring(s string, words []string) (ans []int) {ls, m, n : len(s), len(words), len(words[0])for i : 0; i < n && im*n < ls; i {differ : map[string]int{}for j : 0; j < m; j {differ[s[ij*n:i(j1)*n]…

把握零碎时间,开启长期副业兼职之旅!在家也能轻松赚钱!

转眼间&#xff0c;2024年已悄然走过三分之一。这一年&#xff0c;外界环境似乎并不那么友好&#xff0c;但对我而言&#xff0c;我的月收入仍然相对稳定。我找到的副业让我每月能赚到3000元以上&#xff0c;这让我深感庆幸。 现实中&#xff0c;只依赖主业工资的日子确实艰辛…

【LeetCode热题100】【回溯】分割回文串

题目链接&#xff1a;131. 分割回文串 - 力扣&#xff08;LeetCode&#xff09; 要找出所有分割这个字符串的方案使得每个子串都是回文串&#xff0c;写一个判断回文串的函数&#xff0c;深度遍历回溯去找出所有分割方案&#xff0c;判断分割的子串是否是回文串 class Soluti…