C++11:C++11包括大量的新特性:包括lambda表达式,类型推导关键字auto、decltype,和模板的大量改进。

新的关键字

auto

C++11中引入auto第一种作用是为了自动类型推导

auto的自动类型推导,用于从初始化表达式中推断出变量的数据类型。通过auto的自动类型推导,可以大大简化我们的编程工作

auto实际上实在编译时对变量进行了类型推导,所以不会对程序的运行效率造成不良影响

另外,似乎auto并不会影响编译速度,因为编译时本来也要右侧推导然后判断与左侧是否匹配

  1. auto a; // 错误,auto是通过初始化表达式进行类型推导,如果没有初始化表达式,就无法确定a的类型
  2. auto i = 1;
  3. auto d = 1.0;
  4. auto str = "Hello World";
  5. auto ch = 'A';
  6. auto func = less<int>();
  7. vector<int> iv;
  8. auto ite = iv.begin();
  9. auto p = new foo() // 对自定义类型进行类型推导

auto不光有以上的应用,它在模板中也是大显身手,比如下例这个加工产品的例子中,如果不使用auto就必须声明Product这一模板参数:

  1. template <typename Product, typename Creator>
  2. void processProduct(const Creator& creator) {
  3. Product* val = creator.makeObject();
  4. // do somthing with val
  5. }
  6. .

如果使用auto,则可以这样写:

  1. template <typename Creator>
  2. void processProduct(const Creator& creator) {
  3. auto val = creator.makeObject();
  4. // do somthing with val
  5. }

抛弃了麻烦的模板参数,整个代码变得更加正解了。

decltype

decltype实际上有点像auto的反函数,auto可以让你声明一个变量,而decltype则可以从一个变量或表达式中得到类型,有实例如下:

  1. int x = 3;
  2. decltype(x) y = x;

有人会问,decltype的实用之处在哪里呢,我们接着上边的例子继续说下去,如果上文中的加工产品的例子中我们想把产品作为返回值该怎么办呢?我们可以这样写:

  1. template <typename Creator>
  2. auto processProduct(const Creator& creator) -> decltype(creator.makeObject()) {
  3. auto val = creator.makeObject();
  4. // do somthing with val
  5. }

nullptr

nullptr是为了解决原来C++中NULL的二义性问题而引进的一种新的类型,因为NULL实际上代表的是0,

  1. void F(int a){
  2. cout<<a<<endl;
  3. }
  4. void F(int *p){
  5. assert(p != NULL);
  6. cout<< p <<endl;
  7. }
  8. int main(){
  9. int *p = nullptr;
  10. int *q = NULL;
  11. bool equal = ( p == q ); // equal的值为true,说明p和q都是空指针
  12. int a = nullptr; // 编译失败,nullptr不能转型为int
  13. F(0); // 在C++98中编译失败,有二义性;在C++11中调用F(int)
  14. F(nullptr);
  15. return 0;
  16. }

序列for循环

在C++中for循环可以使用类似java的简化的for循环,可以用于遍历数组,容器,string以及由begin和end函数定义的序列(即有Iterator),示例代码如下:

  1. map<string, int> m{{"a", 1}, {"b", 2}, {"c", 3}};
  2. for (auto p : m){
  3. cout<<p.first<<" : "<<p.second<<endl;
  4. }

Lambda表达式

lambda表达式类似Javascript中的闭包,它可以用于创建并定义匿名的函数对象,以简化编程工作。Lambda的语法如下:

[函数对象参数](操作符重载函数参数)->返回值类型{函数体}

  1. vector<int> iv{5, 4, 3, 2, 1};
  2. int a = 2, b = 1;
  3. for_each(iv.begin(), iv.end(), [b](int &x){cout<<(x + b)<<endl;}); // (1)
  4. for_each(iv.begin(), iv.end(), [=](int &x){x *= (a + b);});     // (2)
  5. 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构造,构造一个包含两种不同类型的数据的容器。比如,如下代码:

  1. auto p = make_pair(1, "C++ 11");

由于在C++11中引入了变长参数模板,所以发明了新的数据类型:tuple,tuple是一个N元组,可以传入1个, 2个甚至多个不同类型的数据

  1. auto t1 = make_tuple(1, 2.0, "C++ 11");
  2. auto t2 = make_tuple(1, 2.0, "C++ 11", {1, 0, 2});

这样就避免了从前的pair中嵌套pair的丑陋做法,使得代码更加整洁

另一个经常见到的例子是Print函数,在C语言中printf可以传入多个参数,在C++11中,我们可以用变长参数模板实现更简洁的Print

  1. template<typename head, typename... tail>
  2. void Print(Head head, typename... tail) {
  3. cout<< head <<endl;
  4. Print(tail...);
  5. }

Print中可以传入多个不同种类的参数,如下:

  1. Print(1, 1.0, "C++11");

更加优雅的初始化方法

在引入C++11之前,只有数组能使用初始化列表,其他容器想要使用初始化列表,只能用以下方法:

  1. int arr[3] = {1, 2, 3}
  2. vector<int> v(arr, arr + 3);

在C++11中,我们可以使用以下语法来进行替换:

  1. int arr[3]{1, 2, 3};
  2. vector<int> iv{1, 2, 3};
  3. map<int, string>{{1, "a"}, {2, "b"}};
  4. string str{"Hello World"};

然后呢…

如果你想了解更多C++11令人兴奋的新特性,我会向你推荐这两个博客:

胡健的C++11系列博文

ToWrting的C++11系列博文

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“完全实现了当前草案的所有内容”;GCCVisual Studio也对C++14的新特性提供了一些支持。

C++11 & C++14 & C++17新特性的更多相关文章

  1. c++17 新特性

    编译环境说明:gcc 8.1 + eclipse +windows 10 eclipse cpp默认支持c++14,做c++17开发时,需要手动进行配置. 1.关键字 1)constexpr c++1 ...

  2. 一文带你看遍 JDK9~14 的重要新特性!

    Java9 发布于 2017 年 9 月 21 日 .作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如 ...

  3. Java 17 新特性:switch的模式匹配(Preview)

    还记得Java 16中的instanceof增强吗? 通过下面这个例子再回忆一下: Map<String, Object> data = new HashMap<>(); da ...

  4. Java 14 有哪些新特性?

    记录为 Java 提供了一种正确实现数据类的能力,不再需要为实现数据类而编写冗长的代码.下面就来看看 Java 14 中的记录有哪些新特性. 作者 | Nathan Esquenazi 译者 | 弯月 ...

  5. C++17 新特性之 std::optional(上)

    最近在学习 c++ 17 的一些新特性,为了加强记忆和理解,把这些内容作为笔记记录下来,有理解不对的地方请指正,欢迎大家留言交流. 引言 在介绍之前,我们从一个问题出发,C++ 的函数如何返回多个值? ...

  6. 从Java 9 到 Java 17 新特性梳理

    Java 9 新的创建集合的方法  // [1, 2, 3, 4]  List<Integer> integers = List.of(1, 2, 3, 4);  // {1,2,3}   ...

  7. Java 11 这 8 个逆天新特性教你写出更牛逼的代码!

    美国时间2018年 09 月 25 日,Oralce 正式发布了 Java 11,这是据 Java 8 以后支持的首个长期版本. 为什么说是长期版本,看下面的官方发布的支持路线图表. 可以看出 Jav ...

  8. Safari 11.0 已发布,新特性都在这儿了!

    Safari 11.0 兼容性 Safari 11.0 可运行于 iOS 11.0 和 macOS 10.1版本的系统环境,同时在macOS 10.12.6 和 10.11.6版本中也可以使用. Hi ...

  9. 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 ...

随机推荐

  1. HTML5 本地存储的用法

    HTML5 的本地存储 API 中的 localStorage 与 sessionStorage 在使用方法上是相同的,区别在于 sessionStorage 在关闭页面后即被清空,而 localSt ...

  2. [Oracle][Corruption]究竟哪些检查影响到 V$DATABASE_BLOCK_CORRUPTION

    根据 471716.1,11g 之后,下列动作如果遇到坏块,都会输出记录到  V$DATABASE_BLOCK_CORRUPTION. -  Analyze table .. Validate str ...

  3. dubbo见解

    调用关系说明 服务容器负责启动,加载,运行服务提供者. 服务提供者在启动时,向注册中心注册自己提供的服务. 服务消费者在启动时,向注册中心订阅自己所需的服务. 注册中心返回服务提供者地址列表给消费者, ...

  4. HTML 样式 (style) 实例

    77.HTML 样式 (style) 实例HTML 的 style 属性style 属性的作用: 提供了一种改变所有 HTML 元素的样式的通用方法. 样式是 HTML 4 引入的,它是一种新的首选的 ...

  5. jenkins pipeline 部署

    一.git 版本控制结合jenkins 发布 sh-4.2$ git branch sh-4.2$ git chekout master sh-4.2$ git tag v1.1 sh-4.2$ gi ...

  6. NodeMCU学习(三) : 进入网络世界

    把NodeMCU连接到路由器网络上 NodeMCU可以被配置为Station模式和softAP模式或者Station + AP模式,当它被配置为Station模式时,就可以去连接Access Poin ...

  7. 7. Reverse Integer【Leetcode by java】

    Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123 Output: 321 Examp ...

  8. 在Ubuntu虚拟机上安装DVWA

    学习资料来源:https://www.neddos.tech/?p=107 最后更新时间: 190122·17:41 1> 什么是DVWA(Damn Vulnerable Web Applica ...

  9. “Linux内核分析”实验三报告

    构造一个简单的Linux系统 张文俊+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10000290 ...

  10. 第二个spring冲刺总结

    讨论成员:罗凯旋.罗林杰.吴伟锋.黎文衷 第二阶段总体是做到了四则运算的demo,,包括APP进入动画,以及界面的基本效果设计,还有能进行综合计算(选择题,可以 自动生成简单,容易,困难 三种难度  ...