1.auto关键字能够在赋值语句里推导类型,decltype能在任意场合下推导类型,但使用时必须在括号内写全表达式。
auto只能用于赋值语句的类型推导,不能直接声明变量(因为无表达式供推导)
auto总是推断出值类型而不是引用类型
auto允许使用const/volatile/&/*等修饰,从而得到新类型
auto&&总是推断出引用类型
decltype (e)形式获得表达式计算结果的值类型
decltype ((e))形式获得表达式计算结果的引用类型,类似auto&&的效果
C++14支持decltype (auto) x=表达式的写法
decltype和auto都可以用来推断类型,但是二者有几处明显的差异:
1.auto忽略顶层const,decltype保留顶层const;
2.对引用操作,auto推断出原有类型,decltype推断出引用;
3.对解引用操作,auto推断出原有类型,decltype推断出引用;
4.auto推断时会实际执行,decltype不会执行,只做分析。总之在使用中过程中和const、引用和指针结合时需要特别小心
// 后置返回值
template <typename It>
auto fcn(It beg, It end) -> decltype(*beg)
{
// 处理序列
return *beg; // 返回序列中一个元素的引用
}
// 后置返回值,为了使用 模板参数 成员,必须用 typename
template <typename It>
auto fcn2(It beg, It end) -> typename remove_reference<decltype(*beg)>::type
{
// 处理序列
return *beg; // 返回序列中一个元素的拷贝
}
2.左值是一个可以用来存储数据的变量,有实际的内存地址(即变量名),表达式结束后依然存在。右值(非左值)是一个“匿名的”,“临时“变量,它在表达式结束时生命周期终止,不能存放数据,可以被修改,也可以不被修改(被const修饰)
判断左值与右值最简单的方式:左值可以使用取地址符& ,右值不能,比如p=&x++ 编译错误,后置++操作返回一个临时对象,不能取地址或赋值,是右值。
可以把右值的内容转移到其他对象中。
T&& 右值引用
T& 左值引用
对一个对象使用右值引用意味着显式标记对象是右值,可以被转移来优化。同时生命周期延长,不会在表达式结束时消失,而是与右值引用绑定在一起。
const T& 可以引用任何对象(增加了常量性)
const T&&语法正确,但因为右值引用是临时的,即将消失,对它增加常量性使其无法修改,也就无法转移,无实际意义。
4种引用示例:
int& r1=++x; //左值引用
int&& r2=++x; //右值引用,引用了自增后的临时对象xvalue
const int& r1=++x; //常量左值引用,也可以引用右值
const int&& r1=++x; //常量右值引用,无实际意义
3.utility头文件里提供了forward函数,用于在泛型编程时,将函数的参数原封不动地转发给其他函数,在使用该函数时函数的参数必须声明为T&&这样类型才可以保持原状。
4.新增 关键字nullptr(是一个类型为nullptr_t的编译期常量对象实例,行为很像指针),表示空指针概念,可完全代替NULL(尽量避免使用这个null宏),可隐式转化为任意类型的指针,也可与指针进行比较运算。
5.统一使用{}初始化变量,称为列表初始化
在函数里{...}可直接返回,类型会自动推导。
6.新式for循环(范围for)本质还是迭代器实现
for (auto x:a){} 访问容器中的元素,有拷贝代价,不能修改元素
for (const auto & x:a){} 访问容器中的元素
使用const auto &或auto&&避免拷贝,
使用auto& 修改元素
7.新式函数声明(允许返回类型后置)
auto func (…) —> T {…} //必须用auto站位
此处T可以是 decltype 表达式
8.泛型编程时函数的返回值的可能类型需要由实际参数决定,所以有必要将返回值类型声明延后
9.在构造/析构等成员函数声明后使用=default显示生命缺省构造/析构函数,编译器更好优化代码,不影响其他构造函数的重载与实现
在构造/析构函数声明后使用=delete显式地禁用拷贝构造函数和拷贝复制构造函数,以组织对象的拷贝,也可用于普通函数,禁止某些形式地重载
10.如果一个成员函数是虚函数,那么后续派生类的同名函数都是虚函数,无需再用virtual修饰。所以只看派生类中很难看出哪些是覆盖了基类的虚函数(当同名函数声明与基类不一致时认为是一个新函数,当用基类指针指向派生类对象时访问会访问基类函数)。override关键字显示地标记虚函数重载,明确程序员的意图:派生类的成员函数名后如果使用了override关键字则一定是虚函数,且声明必须与基类的一致,否则会导致编译错误。
11.在类名后使用final禁止类被继承
在虚函数后使用final,显式禁止该函数在子类中重载,final可与override混用,更好的标记继承体系和虚函数
12.允许类中成员变量(不适用于静态成员变量,且不能用auto进行推导类型)在声明时使用赋值或花括号的方式直接初始化,无需在构造函数里特别指定。
13.委托构造
多个不同形式构造函数用于在不同情况下创建对象,其中有很多重复的初始化成员变量的代码。可将其写在init函数中,在每个构造函数中调用。
把对象的构造工作委托给其他构造函数来完成,委托构造函数可以很好地简化代码。
14.泛型编程
template关键字,泛型编程主要工作在编译期。
15.扩展了using关键字的能力,可完成与typedef相同的工作,如 using int64=long //注意顺序与typedef相反
16.新增关键字constexpr,相当于编译期间的const,可让编译器更好优化代码,可用于编译期常量与编译期常量函数。
17.assert 运行时断言
新增static_assert用于编译期的断言,为false的话编译报错。
18.支持可变参数,允许函数接收任意数量的参数
新增可变参数模板(变参模板),使用…来声明不确定数量的参数。更好地支持编译期的模板元编程。
template<typename …T> class some_class {};模板类
template<typename …T> void some_func {};模板函数
19.lambda表达式(匿名函数对象)
20.并发相关
<atomic>
<mutex>
<thread>
新增thread_local线程本地存储,与extern static类似的变量存储指示标记
thread_local变量在线程启动时构造,线程结束时析构,仅适用于线程需要独立存储的情况。当线程间需要共享访问资源时仍需使用互斥量等机制
21.nonexcept
在函数签名后,表示函数不会抛出异常,降低异常处理的成本,提升运行效率
22.新增内联名字空间
在一个名字空间前用inline修饰,使外部可以无限定直接访问名字空间内成员。
此特性对代码的版本化很有用,可以在多个子名字空间里实现不同版本的功能,而发布时仅用inline对外只报录一个实现,利于隔离版本差异。
23.强类型枚举
之前 当枚举变量可以和其原本的变量类型的变量进行运算
c++11/14不允许这种运算且必须通过类型名限定访问枚举变量::
24.属性
c++14新增 depreciate属性,用于标识已经废弃的变量、函数、类
[[depreciate]] int x=0;//x变量已经废弃
class [[depreciate]] demo{};//demo类已经废弃
25. __CPLUSPLUS宏
一个整型值,可据此判断是哪个c++标准
26.新增long long类型,至少64bit
27.
新增原始字符串 R"(...)"//()内的字符串不会被转义,对正则表达式很有用
28.新增 自定义字面值
可自己定义 有含义的后缀,需重载""运算符
29.>>优先解释为 模板参数列表的结束符,之前优先解释为右移运算符
30.让模板函数也可以使用默认参数
31.union增强,其中的类型可以自定义
32.c++14 0b/0B前缀直接书写二进制数字
33.c++14
允许使用单引号将数字分组,增强可读性
POD (plain old data)普通旧数据类型
本文精炼总结了C++11与C++14引入的重要新特性,包括auto和decltype类型推导、右值引用、泛型编程改进、lambda表达式、并发支持、类型安全增强及编译优化等,旨在帮助开发者快速掌握这两个版本的更新亮点。
1244

被折叠的 条评论
为什么被折叠?



