C++14介绍

C++14标准是 ISO/IEC 14882:2014 Information technology -- Programming languages -- C++ 的简称[1]  。在标准正式通过之前,原名C++1y。

C++14标准的委员会草案N3690于2013年5月15日发表。[2]

2014年8月18日,经过C++标准委员投票,C++14标准获得一致通过。草案文档经过一定的文字润色和修正之后,将在年内提交给ISO作为正式的C++标准发布。

下面描述的特性是委员会草案N3690中所描述的。

中文名
C++14
外文名
C++14
标准编号
ISO/IEC 14882:2014

目录

  1. 新的语言特性
  2. 泛型的Lambda函数
  3. Lambda捕获表达式
  4. 函数返回类型推导
  5. 另一种类型推断
  6. 放松的constexpr限制
  1. 变量模板
  2. 聚合体成员初始化
  3. 运行期确定一维长度的数组
  4. 二进制字面值
  5. 新的标准库特性
  1. 共享的互斥体和锁
  2. Optional值
  3. 关联容器中的异构查找
  4. 标准自定义字面值
  5. 运行期确定长度的定长数组容器
  1. 通过类型寻址多元组
  2. 较小的标准库特性

新的语言特性

编辑

以下为是C++14中被加入语言核心的特性。

泛型的Lambda函数

在C++11中,lambda函数参数需要被声明为具体的类型。C++14放宽了这一要求,允许lambda函数参数类型使用类型说明符auto。

auto lambda = [] (auto x, auto y) {return (x + y); }

尽管使用了C++11的关键字auto,泛型Lambda函数并不遵循auto类型推导的句法,而是遵循模板参数推导的规则(它们相似,但并不是在所有情况下都是相同的)。以上代码与下面的等价:

struct unnamed_lambda

{

template <typename T,typename U>

auto operator()(T x, U y) const

{

return (x+y);

}

};

auto lambda = unnamed_lambda();

Lambda捕获表达式

C++11的lambda函数通过值拷贝或引用捕获在外层作用域声明的变量。这意味着lambda的值成员不可以是只能move的类型。 C++14允许被捕获的成员用任意的表达式初始化。这既允许了通过move捕获,也允许了任意声明lambda的成员,而不需要外层作用域有一个具有相应名字的变量。

这是通过使用一个初始化表达式完成的:

auto lambda=[value{1}] { return value; }

lambda函数 lambda 会返回1,因为value被初始化为1。被声明的捕获变量的类型以与auto相同的方式,根据初始化表达式推断。

使用标准函数std::move可以使之被用以通过move捕获:

auto ptr=std::make_unique<int>(10);//See below for std::make_unique

auto lambda=[ptr{std::move(ptr)}] { return(*ptr); }

声明ptr{std::move(ptr)}使用了两次ptr。第一次使用声明了一个新的变量,但由C++的作用域规则,在初始化表达式求值完毕之前,该变量不在作用域内。所以第二个ptr表示之前在lambda之外声明的变量。

函数返回类型推导

C++11允许lambda函数根据return语句的表达式类型推断返回类型。C++14为所有的函数提供了这个能力。C++14还拓展了原有的规则,使得函数体并不是return expression;形式的函数也可以使用返回类型推导。

为了诱发返回类型推导,函数声明必须将auto作为返回类型,但没有C++11的后置返回类型说明符:

auto DeduceReturnType(); //Return type to be determined.

如果函数实现中含有多个return表达式,这些表达式必须可以推断为相同的类型。

使用返回类型推导的函数可以被前向声明,但在定义之前不可以使用。它们的定义在使用它们的翻译单元之中必须是可用的。

这样的函数中可以存在递归,但递归调用必须在函数定义中的至少一个return语句之后,例如:

auto Correct(int i)

{

if (i == 1)

return (i); // return type deduced as int

else

return (Correct(i-1)+i); // OK to call it now

}

但是下面这样写是错误的:

auto Wrong(int i)

{

if(i!=1)

return (Wrong(i - 1) + i); // Too soon to call this. No prior return statement.

else

return i; // return type deduced as int

}

另一种类型推断

C++11中增加了两种推断类型的方式。auto根据给出的表达式产生具有合适类型的变量。decltype可以计算给出的表达式的类型。但是,decltype和auto推断类型的方式是不同的。特别是,auto总是推断出非引用类型,就好像使用了std::remove_reference一样,而auto&&总是推断出引用类型。然而decltype可以根据表达式的结果类别和表达式的性质推断出引用或非引用类型:

int i;

int &&f();

auto x3a = i; // decltype(x3a) is int

decltype(i) x3d = i; // decltype(x3d) is int

autox 4a = i; // decltype(x4a) is int

decltype((i)) x4d=(i); //decltype(x4d) is int&

auto x5a = f(); //decltype(x5a) is int

decltype(f()) x5d =f(); // decltype(x5d) is int&&

C++14将增加decltype(auto)的语法。这将允许auto声明使用decltype对于给定表达式的推断规则。

decltype(auto)的语法也可以用于返回类型推导,只需使用decltype(auto)代替auto来诱发。

放松的constexpr限制

C++11引入了constexpr函数的概念,这样的函数可以在编译期执行。它们的返回值可以通过计算所需的常量表达式(如整型的模板参数)得出。然而C++11要求constexpr函数只含有一个将被返回的表达式(也可以还含有static_assert声明等其它语句,但允许的语句类型很少)。

C++14将放松这些限制。constexpr函数将可以含有以下内容:

  • 任何声明,除了:
    • static或thread_local变量。
    • 没有初始化的变量声明。
  • 条件分支语句if和switch。goto是不允许的。
  • 所有的循环语句,包括基于范围的for循环。
  • 表达式可以改变一个对象的值,如果该对象的生命期在常量表达式函数内开始。包括对有constexpr声明的任何非const非静态成员函数的调用。

对于调用非constexpr函数的限制仍然存在。所以如果使用基于范围的for循环,begin和end的重载必须自身是constexpr。值得注意的是,std::initializer_list在本地和全局都具有constexpr声明的begin/end函数。

此外,C++11指出,所有被声明为constexpr的非静态成员函数也隐含声明为const(即函数不能修改*this的值)。这点已经被删除,非静态成员函数可以为非const。然而,只有当对象的生命期在常量表达式求值中开始,非const的constexpr成员函数才可以修改类成员。

变量模板

C++之前的版本中,模板可以是函数模板类模板。C++14还也可以创建变量模板。模板的一般规则,包括特化都适用于变量模板的声明和定义。[3]

聚合体成员初始化

C++11新增member initializer,这是一个表达式,被应用到类作用域的成员上,如果构造函数没有初始化这个成员。聚合体的定义被改为明确排除任何含有member initializer的类,因此,他们不允许使用聚合初始化。

C++14将放松这一限制,这种类型也允许聚合初始化。如果花括号初始化列表不提供该参数的值,member initializer会初始化它。

运行期确定一维长度的数组

C++11和之前的标准中,在堆栈上分配的数组被限制为拥有一个固定的、编译期确定的长度。C++14允许在堆栈上分配的一个数组的最后一维具有运行期确定的长度。

运行期确定长度的数组不可以作为对象的一部分,也不可以具有全局存储期,他们只能被声明为局部变量。运行期确定长度的数组也可以使用C++11的基于范围的for循环。

二进制字面值

C++14的数字可以用二进制形式指定。其格式使用前缀0b或0B。这样的语法也被Java、PythonD语言使用。

新的标准库特性

编辑

共享的互斥体和锁

C++14增加了一类共享的互斥体和相应的共享锁。[4-5]

Optional值

C++14增加了一个optional类型,其值可能存在或不存在。这一类型基于Boost的boost::optional类,而添加了C++11和C++14中的新特性,诸如移动和in-place构造。它不允许用在引用类型上。类被专门的设计为一个literal type(如果模板参数本身是一个literal type),因此,在必要的情况下含有constexpr构造函数。

关联容器中的异构查找

C++标准库定义了四个关联容器类。set和multiset允许使用者根据一个值在容器中查找对应的的同类型的值。map和multimap容器允许使用者指定键(key)和值(value)的类型,根据键进行查找并返回对应的值。然而,查找只能接受指定类型的参数,在map和multimap中是键的类型,而在set和multiset容器中就是值本身的类型。

C++14允许通过其他类型进行查找,只需要这个类型和实际的键类型之间可以进行比较操作。在operator<被重载的情况下,这允许一个键为std::string的map与一个键为const char* 的map进行比较。

为保证向后兼容性,这种异构查找只在相应关联容器的比较运算符允许的情况下有效。标准库类 std::less(set和map到默认比较算符)与std::greater也可以被用来进行异构查找。

标准自定义字面值

C++11定义了自定义字面值的语法,但标准库没有使用其中的任何一个。C++14增加了以下标准字面值:

  • "s",用于创建各种std::basic_string类型。
  • "h"、"min"、"s"、"ms"、"us"、"ns",用于创建相应的std::chrono::duration时间间隔。

两个"s"互不干扰,因为表示字符串的只能对字符串字面值操作,而表示秒的只针对数字。

运行期确定长度的定长数组容器

std::vector类型表示一个可变长度的数组,可以根据需要增长和收缩。C++11的std::array表示一个固定长度的数组,其长度在编译时确定。

C + +14将添加std::dynarray类型,它代表一个固定长度的数组,其大小在运行期构造对象时确定。std::dynarray类被明显地设计为当它被放置在栈上时(直接放置在栈上,或作为另一个栈对象的成员),可以使用栈内存而不是堆内存

通过类型寻址多元组

C++11引入的std::tuple类型允许不同类型的值的聚合体用编译期整型常数索引。C++14还允许使用类型代替常数索引,从多元组中获取对象。若多元组含有多于一个这个类型的对象,将会产生一个编译错误:

tuple <string, string, int> t ("foo", "bar", 7);

int i = get<int>(t); // i == 7

int j = get<2>(t); // Same as before: j == 7

string s = get<string>(t); // Compiler error due to ambiguity

较小的标准库特性

std::make_unique可以像 std::make_shared一样使用,用于产生std::unique_ptr对象。

std::integral_constant将会具有一个返回常量值的operator()重载。

全局std::begin/std::end函数之外,将会增加std::cbegin/std::cend函数,它们返回一个范围的开始/结束常量迭代器

时间: 2024-11-15 10:04:05

C++14介绍的相关文章

[Java面试五]Spring总结以及在面试中的一些问题.

1.谈谈你对spring IOC和DI的理解,它们有什么区别? IoC Inverse of Control 反转控制的概念,就是将原本在程序中手动创建UserService对象的控制权,交由Spring框架管理,简单说,就是创建UserService对象控制权被反转到了Spring框架 DI:Dependency Injection 依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件 面试题: IoC 和 DI的区别? IoC 控制反转,指将对象的创建权,反

ASP.NET管道

1.ASP.NET生命周期 2.Http运行时 3.Http管道技术 a)inetinfo.exe b)asp.net_isapi.dll c)aspnet_wp.exe d)HttpHandler e)HttpModule 4.实现Httphandler的使用 5.ASP.NET生命周期 6.(IIS)Web服务器(inetinfo.exe): 1.只有少数几种被客户端请求的资源类型由iis直接处理,如对Html页面,文本文件,jpeg和gif图像的传入请求 2.对ASP.NET资源(*.as

网页搜集系统

自1994年万维网出现后,互联网上的网页数量就呈指数级生长,到目前为止,短短二十余年,互联网上就有成百上千亿网页.如何在这海量的网页中搜索下载具有对特定场景有价值的网页?使用什么样的策略能保证网页不会出现重复?如何保证爬虫程序的高并发爬取?如何在网页中提取关键点等等问题,这是本篇博客重点描述的内容. 1.1 万维网结构分析 把万维网看作是一个相互连通的连通图,每个网页看作一个节点,链接看作为边,其中任意一个网页可被其它网页所链接,这种链接叫"反向链接",这个网页也可以链接到其它网页,这

python学习第六天 - 列表(数组)

python当中的数组与java,c不太一样,数组相当于一个列表,一个列表中可以有,整型,字符串,浮点型等等. 定义格式如下: >>> list = [123,'小甲鱼',3.14] >>> list [123, '小甲鱼', 3.14] 介绍几种向列表中添加元素的方法 1.append() :向列表中增加新的元素,一次只能添加一个元素,默认添加到列表的末尾 >>> list.append('黑夜') >>> list [123, '

spring学习 8-面试spring 问题

1.谈谈你对spring IOC和DI的理解,它们有什么区别? IoC Inverse of Control 反转控制的概念,就是将原本在程序中手动创建UserService对象的控制权,交由Spring框架管理,简单说,就是创建UserService对象控制权被反转到了Spring框架 DI:Dependency Injection 依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件 面试题: IoC 和 DI的区别? IoC 控制反转,指将对象的创建权,反

JSP相关的一些问题与分析

JSP作为JavaEE最流行的表现层技术,并非不可替代,实际上随着JavaEE技术的发展,又出现了FreeMaker.Velocity等表现层技术,虽然这些技术可以取代JSP作为表现层的角色,但是JSP作为最早的JavaEE规范之一,JSP依然广泛用于各种Java应用之中. JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它是由Sun Microsystems公司倡导.许多公司参与一起建立的一种动态网页技术标准.JSP技术有点类似

ROS关于cv_brige的使用

最近想使用OpenCV 和ROS实现点云的拼接,实现三维重建,那么在学习了kinect的基本的使用方法以后我们知道,直接使用ROS 的包即可得到点云,深度图,rgb图等信息, roslaunch openni_launch openni.launch(深度图彩色图,还有点云都获取了) rosrun openni_camera openni_node   (深度图与彩色图) 那么实现点云的拼接就需要使用cv_bridge把ROS 的数据格式转为Opencv可以使用的数据格式.即是一个提供ROS和O

Asp.Net生命周期和Http管道技术

本篇主要介绍一下内容: 1.ASP.NET生命周期 2.Http运行时 3.Http管道技术 a)inetinfo.exe b)asp.net_isapi.dll c)aspnet_wp.exe d)HttpHandler e)HttpModule 4.实现Httphandler的使用 5.ASP.NET生命周期 6.(IIS)Web服务器(inetinfo.exe): 1.只有少数几种被客户端请求的资源类型由iis直接处理,如对Html页面,文本文件,jpeg和gif图像的传入请求 2.对AS

[Java面试一]Spring总结以及在面试中的一些问题.(转发:http://www.cnblogs.com/wang-meng/p/5701982.html)

1.谈谈你对spring IOC和DI的理解,它们有什么区别? IoC Inverse of Control 反转控制的概念,就是将原本在程序中手动创建UserService对象的控制权,交由Spring框架管理,简单说,就是创建UserService对象控制权被反转到了Spring框架 DI:Dependency Injection 依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件 面试题: IoC 和 DI的区别? IoC 控制反转,指将对象的创建权,反