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 ...
随机推荐
- Hadoop日记Day16---命令行运行MapReduce程序
一.代码编写 1.1 单词统计 回顾我们以前单词统计的例子,如代码1.1所示. package counter; import java.net.URI; import org.apache.hado ...
- Hadoop开发第2期---虚拟机中搭建Linux
注:关于如何将hadoop源码导入Eclipse详见http://pan.baidu.com/s/1hq8ArUs 一.Hadoop配置软件(我的电脑是Windows7旗舰--64bit) 1. VM ...
- centos7 部署 nginx+tomcat+MariaDB 环境并安装安全狗,使用natapp隧道
jdk安装: -openjdk 参考:https://blog.csdn.net/dhr201499/article/details/81626466 tomcat安装: 使用版本:8.5.37 参考 ...
- Security4:授予查看定义,执行SP和只读数据的权限
SQL Server数据库有完善的权限管理机制,对于存储过程,其权限分为查看定义,执行和修改,查看SP定义的权限是:VIEW DEFINITION ,执行存储过程的权限是:EXECUTE,修改SP的权 ...
- nginx location 正则匹配
nginx 统计语句1.根据访问IP统计UV awk '{print $1}' access.log|sort | uniq -c |wc -l2.统计访问URL统计PV awk '{print $7 ...
- 教你如何自学UI设计
一.常用的UI相关工具软件 PS Adobe Illustrator(AI) C4D AE Axure Sketch 墨刀 Principle Cutterman PxCook Zeplin 蓝湖 X ...
- Overlay技术
- python爬虫-使用cookie登录
前言: 什么是cookie? Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密). 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想 ...
- Scrum Meeting NO.5
Scrum Meeting No.5 1.会议内容 暂时料理完了编译,可以写软工了.说多了都是泪T_T 2.任务清单 徐越 序号 近期的任务 进行中 已完成 1 修改url名.参数 √ 2 学习Jso ...
- 《Linux内核分析》 第四节 扒开系统调用的三层皮(上)
<Linux内核分析> 第四节 扒开系统调用的三层皮(上) 张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com ...