C++11 & C++14 & C++17新特性
C++11:C++11包括大量的新特性:包括lambda表达式,类型推导关键字auto、decltype,和模板的大量改进。
新的关键字
auto
C++11中引入auto第一种作用是为了自动类型推导
auto的自动类型推导,用于从初始化表达式中推断出变量的数据类型。通过auto的自动类型推导,可以大大简化我们的编程工作
auto实际上实在编译时对变量进行了类型推导,所以不会对程序的运行效率造成不良影响
另外,似乎auto并不会影响编译速度,因为编译时本来也要右侧推导然后判断与左侧是否匹配。
- auto a; // 错误,auto是通过初始化表达式进行类型推导,如果没有初始化表达式,就无法确定a的类型
- auto i = 1;
- auto d = 1.0;
- auto str = "Hello World";
- auto ch = 'A';
- auto func = less<int>();
- vector<int> iv;
- auto ite = iv.begin();
- auto p = new foo() // 对自定义类型进行类型推导
auto不光有以上的应用,它在模板中也是大显身手,比如下例这个加工产品的例子中,如果不使用auto就必须声明Product这一模板参数:
- template <typename Product, typename Creator>
- void processProduct(const Creator& creator) {
- Product* val = creator.makeObject();
- // do somthing with val
- }
- .
如果使用auto,则可以这样写:
- template <typename Creator>
- void processProduct(const Creator& creator) {
- auto val = creator.makeObject();
- // do somthing with val
- }
抛弃了麻烦的模板参数,整个代码变得更加正解了。
decltype
decltype实际上有点像auto的反函数,auto可以让你声明一个变量,而decltype则可以从一个变量或表达式中得到类型,有实例如下:
- int x = 3;
- decltype(x) y = x;
有人会问,decltype的实用之处在哪里呢,我们接着上边的例子继续说下去,如果上文中的加工产品的例子中我们想把产品作为返回值该怎么办呢?我们可以这样写:
- template <typename Creator>
- auto processProduct(const Creator& creator) -> decltype(creator.makeObject()) {
- auto val = creator.makeObject();
- // do somthing with val
- }
nullptr
nullptr是为了解决原来C++中NULL的二义性问题而引进的一种新的类型,因为NULL实际上代表的是0,
- void F(int a){
- cout<<a<<endl;
- }
- void F(int *p){
- assert(p != NULL);
- cout<< p <<endl;
- }
- int main(){
- int *p = nullptr;
- int *q = NULL;
- bool equal = ( p == q ); // equal的值为true,说明p和q都是空指针
- int a = nullptr; // 编译失败,nullptr不能转型为int
- F(0); // 在C++98中编译失败,有二义性;在C++11中调用F(int)
- F(nullptr);
- return 0;
- }
序列for循环
在C++中for循环可以使用类似java的简化的for循环,可以用于遍历数组,容器,string以及由begin和end函数定义的序列(即有Iterator),示例代码如下:
- map<string, int> m{{"a", 1}, {"b", 2}, {"c", 3}};
- for (auto p : m){
- cout<<p.first<<" : "<<p.second<<endl;
- }
Lambda表达式
lambda表达式类似Javascript中的闭包,它可以用于创建并定义匿名的函数对象,以简化编程工作。Lambda的语法如下:
[函数对象参数](操作符重载函数参数)->返回值类型{函数体}
- vector<int> iv{5, 4, 3, 2, 1};
- int a = 2, b = 1;
- for_each(iv.begin(), iv.end(), [b](int &x){cout<<(x + b)<<endl;}); // (1)
- for_each(iv.begin(), iv.end(), [=](int &x){x *= (a + b);}); // (2)
- for_each(iv.begin(), iv.end(), [=](int &x)->int{return x * (a + b);});// (3)
- []内的参数指的是Lambda表达式可以取得的全局变量。(1)函数中的b就是指函数可以得到在Lambda表达式外的全局变量,如果在[]中传入=的话,即是可以取得所有的外部变量,如(2)和(3)Lambda表达式
- ()内的参数是每次调用函数时传入的参数。
- ->后加上的是Lambda表达式返回值的类型,如(3)中返回了一个int类型的变量
- 下面是各种变量截取的选项:
- [] 不截取任何变量
- [&} 截取外部作用域中所有变量,并作为引用在函数体中使用
- [=] 截取外部作用域中所有变量,并拷贝一份在函数体中使用
- [=, &foo] 截取外部作用域中所有变量,并拷贝一份在函数体中使用,但是对foo变量使用引用
- [bar] 截取bar变量并且拷贝一份在函数体重使用,同时不截取其他变量
- [this] 截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。
变长参数的模板
我们在C++中都用过pair,pair可以使用make_pair构造,构造一个包含两种不同类型的数据的容器。比如,如下代码:
- auto p = make_pair(1, "C++ 11");
由于在C++11中引入了变长参数模板,所以发明了新的数据类型:tuple,tuple是一个N元组,可以传入1个, 2个甚至多个不同类型的数据
- auto t1 = make_tuple(1, 2.0, "C++ 11");
- auto t2 = make_tuple(1, 2.0, "C++ 11", {1, 0, 2});
这样就避免了从前的pair中嵌套pair的丑陋做法,使得代码更加整洁
另一个经常见到的例子是Print函数,在C语言中printf可以传入多个参数,在C++11中,我们可以用变长参数模板实现更简洁的Print
- template<typename head, typename... tail>
- void Print(Head head, typename... tail) {
- cout<< head <<endl;
- Print(tail...);
- }
Print中可以传入多个不同种类的参数,如下:
- Print(1, 1.0, "C++11");
更加优雅的初始化方法
在引入C++11之前,只有数组能使用初始化列表,其他容器想要使用初始化列表,只能用以下方法:
- int arr[3] = {1, 2, 3}
- vector<int> v(arr, arr + 3);
在C++11中,我们可以使用以下语法来进行替换:
- int arr[3]{1, 2, 3};
- vector<int> iv{1, 2, 3};
- map<int, string>{{1, "a"}, {2, "b"}};
- string str{"Hello World"};
然后呢…
如果你想了解更多C++11令人兴奋的新特性,我会向你推荐这两个博客:
原文链接:http://my.oschina.net/wangxuanyihaha/blog/183151
C++14:C++14的主要特性可以分为三个领域:Lambda函数、constexpr和类型推导。
Lambda函数
C++14的泛型Lambda使编写如下语句成为可能:
auto lambda = [](auto x, auto y) {return x + y;};
而另一方面,C++11要求Lambda参数使用具体的类型声明,比如:
auto lambda = [](int x, int y) {return x + y;};
此外,新标准中的std::move函数可用于捕获Lambda表达式中的变量,这是通过移动对象而非复制或引用对象实现的:
std::unique_ptr ptr(new int());
auto lambda = [value = std::move(ptr)] {return *value;};
constexpr
在C++11中,使用constexpr声明的函数可以在编译时执行,生成一个值,用在需要常量表达式的地方,比如作为初始化模板的整形参数。C++11的constexpr函数只能包含一个表达式,C++14放松了这些限制,支持诸如if 和switch等条件语句,支持循环,其中包括基于区间(range)的for 循环。
类型推导
C++11仅支持Lambda函数的类型推导,C++14对其加以扩展,支持所有函数的返回类型推导:
auto DeducedReturnTypeFunction();
因为C++14是强类型语言,有些限制需要考虑:
- 如果一个函数的实现中有多个返回语句,这些语句一定要推导出同样的类型。
- 返回类型推导可以用在前向声明中,但是在使用它们之前,翻译单元中必须能够得到函数定义。
- 返回类型推导可以用在递归函数中,但是递归调用必须以至少一个返回语句作为先导,以便编译器推导出返回类型。
C++14带来的另一个类型推导方面的改进是decltype(auto)语法,它支持使用与auto同样的机制计算给定表达式的类型。auto和 decltype在C++11中就已经出现了,但是它们在推导类型时使用了不同的机制,这可能会产生不同的结果。
C++14中的其他改变包括可以声明变量模板,支持使用0b或0B前缀来声明二进制字面常量。InfoQ已经介绍过C++14中可能破坏C++11程序的其他小型修改。
主流C++编译器对新语言特性的支持正在有条不紊地开发:Clang“完全实现了当前草案的所有内容”;GCC和Visual Studio也对C++14的新特性提供了一些支持。
C++11 & C++14 & C++17新特性的更多相关文章
- c++17 新特性
编译环境说明:gcc 8.1 + eclipse +windows 10 eclipse cpp默认支持c++14,做c++17开发时,需要手动进行配置. 1.关键字 1)constexpr c++1 ...
- 一文带你看遍 JDK9~14 的重要新特性!
Java9 发布于 2017 年 9 月 21 日 .作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如 ...
- Java 17 新特性:switch的模式匹配(Preview)
还记得Java 16中的instanceof增强吗? 通过下面这个例子再回忆一下: Map<String, Object> data = new HashMap<>(); da ...
- Java 14 有哪些新特性?
记录为 Java 提供了一种正确实现数据类的能力,不再需要为实现数据类而编写冗长的代码.下面就来看看 Java 14 中的记录有哪些新特性. 作者 | Nathan Esquenazi 译者 | 弯月 ...
- C++17 新特性之 std::optional(上)
最近在学习 c++ 17 的一些新特性,为了加强记忆和理解,把这些内容作为笔记记录下来,有理解不对的地方请指正,欢迎大家留言交流. 引言 在介绍之前,我们从一个问题出发,C++ 的函数如何返回多个值? ...
- 从Java 9 到 Java 17 新特性梳理
Java 9 新的创建集合的方法 // [1, 2, 3, 4] List<Integer> integers = List.of(1, 2, 3, 4); // {1,2,3} ...
- Java 11 这 8 个逆天新特性教你写出更牛逼的代码!
美国时间2018年 09 月 25 日,Oralce 正式发布了 Java 11,这是据 Java 8 以后支持的首个长期版本. 为什么说是长期版本,看下面的官方发布的支持路线图表. 可以看出 Jav ...
- Safari 11.0 已发布,新特性都在这儿了!
Safari 11.0 兼容性 Safari 11.0 可运行于 iOS 11.0 和 macOS 10.1版本的系统环境,同时在macOS 10.12.6 和 10.11.6版本中也可以使用. Hi ...
- c++11 C++14 C++17
Since C++11, WG21, the ISO designation for the C++ standard, try to shipped the standard every 3 ye ...
随机推荐
- 【转载】VS配置路径和宏
原文路径:http://blog.csdn.net/puttytree/article/details/7838419 在介绍项目配置之前,先说明两点 1. 项目配置中,最好不要使用相对路径,更不要使 ...
- TMS320VC5509片内ADC采集
1. ADC采集比较简单,内部的10位的ADC,AIN0-AIN3的输入,主要是用的CSL的库函数#include <csl_adc.h> ; Uint16 samplestoraage[ ...
- shellcode 初次使用笔记
winXP SP3 环境 (xp环境默认没开启栈不可执行机制,比较方便破解,如果已开启了,请自行百度如何关闭) dig.exe 目标文件 x86dbg调试工具 python 环境 打开准备好的目标软件 ...
- Unity Inspector添加自定义按钮(Button)
在Unity开发游戏的时候,为了有一个更快更方便的工作流,我们往往会在Editor下开发一些方便实用的工具.在工具中,用到最多,最关键的就是按钮,它是工具的首席执行官.下面就用最简单的代码来演示添加一 ...
- 初始化Weex项目遇到的问题记录
Weex 提供了一个命令行工具 weex-toolkit 来帮助开发者使用 Weex.它可以用来快速创建一个空项目.初始化 iOS 和 Android 开发环境.调试.安装插件等操作. 目前 weex ...
- 甲题题解-1116. Come on! Let’s C (20)-(素数筛选法)
用vis标记出现过的id,checked标记询问过的id.至于如何判断排名为素数,用素数筛选法预处理一下即可,水题. #include <iostream> #include <cs ...
- C. Smallest Word
链接 [http://codeforces.com/contest/1043/problem/C] 题意 给你一个只包含a,b的字符串,有一种操作把第1个字符到第i个字符的子串进行反转,问要使最后字符 ...
- Daily Scrumming* 2015.12.13(Day 5)
一.团队scrum meeting照片 二.今日总结 姓名 WorkItem ID 工作内容 签入链接以及备注说明 江昊 任务1063 查找与学习前端工具库,并写出一篇指导文档 https://gi ...
- Beta阶段敏捷冲刺②
1.提供当天站立式会议照片一张. 每个人的工作 (有work item 的ID),并将其记录在码云项目管理中: 1.1昨天已完成的工作. 姓名 昨天已完成的工作 徐璐琳 完成设置界面的排版 祁泽文 实 ...
- 第十周PSP&进度条
PSP 一.表格: D日期 C类型 C内容 S开始时间 E结束时间 I时间间隔 T净时间(mins) 预计花费时间(mins) 11月17号 站立会议 分配任务 13:00 13:30 0 3 ...