nullptr
- 传统的C头文件
stddef.h
定义NULL
#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
由于NULL的二义性,在f(int),f(char *)
里调用f(NULL)
会调用int版本,不符合预期。为了避免类似错误,有的编译器做了自己的改进,比如g++直接将NULL转换为内部__null
标志符,编译时遇到二义性就报错。
- C++11为了兼容性考虑,没有消除0的二义性,引入nullptr“指针空值常量”,类型是
nullptr_t
typedef decltype(nullptr) nullptr_t
- nullptr是关键字,也是有类型的,可以被隐式转换为指针类型,
f(nullptr)
就可以调用指针版本。由于nullptr_t内置类型的存在,因此可以定义和nullptr等价的指针空值类型的变量,和nullptr没有区别。 - nullptr_t类型的数据可以转换为任意类型,不能转换为非指针类型,不使用算术运算符,可以用于关系运算符
- 除了nullptr_t内置类型,c++11还有许多其他的内置类型。
- 在模板里,nullptr_t会作为普通类型进行推导。
默认函数控制
- C++自定义类,编译器会默认生成一些成员函数。构造、拷贝、析构、赋值、移动构造、移动拷贝以及操作符函数(, & && * -> new delete ->*) ,如果用户自定了相应版本的函数,编译器就不再生成缺省的版本。
- 自定义函数后,编译器不生成缺省版本,可能导致类型不再是POD。为此,C++11重用关键字default,显示指定编译器生成缺省版本的函数。
- C++11提供关键字delete,指定编译器不生成缺省版本的函数。在单例时可以使用delete而不是放入private。显式删除还能避免编译器隐式转换带来的问题。显式删除new操作符可以达到避免在堆上分配class对象。删除析构函数可以为对象在指定内存位置进行内存分配,配合placement new构建,不再需要析构函数。
lambda函数
- 语法定义
[capture](parameters)mutable->return_type{statement}
- 默认情况下lambda函数是const版本,使用mutable可取消const。
C++11标准,在块作用域外,捕捉列表必须是空。块作用域中仅能捕捉负作用域中的自动变量。
C++11之前使用仿函数实现类似lambda函数功能,实际上,仿函数是lambda实现的一种方式,有时lambda出错,编译时出现一些构造函数的信息,就是这种实现方式造成的。仿函数可以跨越作用域的。
- lambda函数在C++11标准中默认是内联的,被定义为一个闭包(closure class),每个lambda产生一个临时对象,并不是一个函数。lambda可以转化为一个函数指针,不过要求不能有捕捉列表。