
C++14标准是 ISO/IEC 14882:2014 Information technology -- Programming languages -- C++ 造声工仅北攻的简称 。在标准正式通过之前,原名C++1y。
- 中文名称 C++14
- 外文名称 C++14
- 标准编号 ISO/IEC 14882:2014
新的语言特性
以下为是C++14中被加入语催您蜜台言核心的特性。
C++14标准的委员会草案N3690于2013年5月15日发表。
2014年8月18日,经过C++标准委员投票,C++14标准获理得一致通过。草案文档经过一定的文字润色和修正之后,将在年内提交给ISO作为正式的C++标准发布。
下面描述的特性是委员会草案N3690中所描来自述的。
Lambda函数
360百科 在C++11中,lambda函数参数需要被声明为具体的类型。C++14放宽了这一要求京振查叶边阿鲜火,允许lambda函数参数类婶嚷型使用类型说明符auto。
尽管使用了C++11的关键字auto,泛型Lambda函数并不遵循auto类型推导的句法,而是遵循模板参数推导的规则(它们相似,但并不是在所有情况下都是相同的)。以上代码与下面的等价:
Lambda捕获表达式
C++11的棕院付lambda函数通过值拷贝或引用捕获在外层定求树道余业先板施作用域声明的变量。这意味着lambda的值成员不可以是只能move的类型。 C++14允许被捕获的成员用任影轻著里字迅意的表达式初始化。这既允许了通过move捕获,也允许了任意声明lambda的成员,而不需要外层作用域有一个具有相应名字的变量。
这是通过使用一个初始化表达式完成的:
lambda函数 lambda 会返回1,因为valu异里鲜例e被初始化为1。被声明的捕获变量的类型以与auto相同的方式,根据初始化表达式推断。
使用标准函数父std::move可以使之被用以通过move捕获:
声明ptr{std::坐接move(ptr)}使用了两次ptr。第一次使用声明了一个新的变量,但由C++的作用域规则,在初始化表达式求值完毕之前,该变量不在作用域内。所以第二个ptr表示之前在lambda之外声明的变量。
函数的返回值类型推导
C++11允许lam谈bda函数根据return语句的表达式类型推断返回类型。C++14为所有的函数提供了这个能茅厚匪力炼套旬府。C++14还国拓展了原有的规则,使得函数固仍百首争镇体并不是return expression;形式的函数也可以使用返回类型参阻酸胶推导。
为了诱发返回类型推导,函数声明必须将auto作为返回类型,但没有C++11的后置返回类型说明符:
如果函数实现中含有多个return表达式,这些表达式必须可以推断为相同的类型。
使用返回类型遥府束推导的函数可以被前向声明,但在定义之前不可以使用。它们的定义在使用它们的翻译单元之中必须是可用的。
这样的函劝协走端持促数中可以存在递归,但递归调用必须在函数定义中的至少一个ret川端凯策观营松刻静营月urn语句之后,例如:
但是下面这样写会引发一个Error:
其它类型推断
C++11中增加了两种推断类型的方式。auto根据给出的表达式产生具有合适类型的变煤别老量。decltype可以计算婷修标抓往求初题样给出的表达式的类型。但是,decltype和auto推断类型的方式是不同的。特别是,auto总是推断出非引用类型,就好像使用了std::remove_reference一样,而auto&&总是推断出引用类型。然而decltype可以根据表达式的结果类别和表达式的性质推断出引用或非引用类型:
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还也可以创建变量模板。模板的一般规则,包括特化都适用于变量模板的声明和定义。
聚合初始化
C++11新增类内成员默认初始值,这是一个表达式,被应用到类作用域的成员上,如果构造函数没有初始化这个成员。聚合体的定义被改为明确排除任何含有类内成员默认初始值的类,因此,他们不允许使用聚合初始化。
C++14将放松这一限制,这种类型也允许聚合初始化。如果花括号初始化列表不提供该参数的值,类内成员默认初始值会初始化它。
二进制字面值
C++14的数字可以用二进制形式指定。其格式使用前缀0b或0B。这样的语法也被Java、Python和D语言使用。
新标准库特性
共享和互斥
C++14增加了一类共享的互斥体和相应的共享锁。
异构查找
C++标准库定义了四个关联容器类。set和multiset允许使用者根据一个值在容器中查找对应的的同类型的值。map和multimap容器允许使用者指定键(key)和值(value)的类型,根据键进行查找并返回对应的值。然而,查找只能接受指定类型的参数,在map和multimap中是键的类型,而在set和multiset容器中就是值本身的类型。
C++14允许通过其他类型进行查找,只需要这个类型和实际的键类型之间可以进行比较操作。在小于运算符被重载的情况下,这允许一个键为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"互不干扰,因为表示字符串的只能对字符串字面值操作,而表示秒的只针对数字。
寻址多元组
C++11引入的std::tuple类型允许不同类型的值的聚合体用编译期整型常数索引。C++14还允许使用类型代替常数索引,从多元组中获取对象。若多元组含有多于一个这个类型的对象,将会产生一个编译错误:
tuple t ("foo", "bar", 7);
int i = get(t); // i == 7
int j = get<2>(t); // Same as before: j == 7
string s = get(t); // Compiler error due to ambiguity
其它函数特性
std::make_unique可以像 std::make_shared一样使用,用于产生std::unique_ptr对象。
std::integral_constant将会具有一个返回常量值的调用运算符重载。
全局std::begin/std::end函数之外,将会增加std::cbegin/std::cend函数,它们返回一个范围的开始/结束常量迭代器。