类型推导 Auto
利用模板可以将不同类型的变量相加,之后用auto接收结果进行类型推导
遍历容器时,原先的通过迭代器遍历
现在可以通过一种新的方式来遍历
空指针 nullptr
之前的NULL空指针实质上是一个int型的0,现在C++11新增nullptr_t空值类型,它只有一个空值常量nullptr
typedef decltype(nullptr) nullptr_t;
完全区分0和空指针
void f(char *p)
{
cout << "f(char *)" << endl;
}
void f(int)
{
cout << "f(int)" << endl;
}
int main()
{
f(nullptr);//f(char *)
f(0); //f(int)
return 0;
}
nullptr_t类型数据可以隐式转换为任何一个指针类型
nullptr_t类型数据不能转换为非指针类型,即使强制转换也不可以,所以不适用于算术运算表达式
nullptr_t类型数据可以用于关系运算表达式,但仅能与nullptr_t类型数据或者指针类型数据进行比较
f(nullptr)并不会被推导成某种基本类型的指针(或者void*指针),因此要让编译器成功推导出nullptr的类型,必须做显式的类型转换。但是nullptr跟正常指针一样占4字节
template<typename T>
void f(T* t)
{
cout << "f(T* t)" << endl;
}
template<typename T>
void fa(T t)
{
cout<<"fa(T t)"<<endl;
}
int main()
{
//f(nullptr);//编译失败 nullptr类型是nullptr_t,而不是指针
f((int*)nullptr);//T = int
fa(0);//T = int
fa(nullptr);// T = nullptr_t
fa((int*)nullptr);//T = int*
return 0;
}
强类型枚举enum class
之前的枚举类型容易命名冲突
现在C++11新特性增加强类型枚举
构造函数的相互调用 delegating constructor
在C++11之前是不允许构造函数之间互相调用的,有点繁琐
C++11可以进行构造函数相互调用
禁止重写 final
正常的继承虚函数版本
加上final禁止虚函数被重写
在类声明后面加上final 类禁止被继承
显式声明重写 override
可以看到B在继承A的时候,并没有重写f()函数,是因为少写了一个const,这样B认为f()不是继承来的。而是自己拥有的
将const加上之后
此时可以用override进行验证,避免编译通过未重写虚函数
定义成员初始值
默认函数控制
对于自定义类,编译器会生成默认函数:
1、构造函数
2、拷贝构造函数
3、拷贝赋值函数(operator =)
4、移动构造函数
5、移动拷贝函数
6、析构函数
默认构造函数 default
正常的话,没有写构造函数的话,会自动生成无参数的构造函数,但是要是写出了自定义构造函数后,编译器不会再生成无参数构造函数,此时就可以用default强制编译器生成无参数构造函数
删除构造函数 delete
之前想要隐藏构造函数的方法是直接将构造函数声明成private,现在可以在public下用delete来声明,这样不会对友元类有影响
“=default” 与 “=deleted”(缺省即默认)
C++11标准称“=default” 修饰的函数为显式缺省(explicit defaulted)函数,而称 “=delete” 修饰的函数为显式删除函数。
C++11引用显式缺省和显式删除是为了增强对类默认函数的控制,让程序员能够更加精细地控制默认版本的函数。事实上,显式缺省不仅可以用于在类的定义中修饰成员函数,也可以在类定义之外修饰成员函数。
class DefaultedOptr{
public:
//使用"=default"来产生缺省版本
DefaultedOptr() =default;
//这里没使用"=default"
DefaultedOptr& operator=(const DefaultedOptr&);
};
//在类定义外用"=default"来指明使用缺省版本
inline DefaultedOptr& DefaultedOptr:: operator=(const DefaultedOptr&) =default;
我们就可以通过delete对一些危险的、不应该发生的隐式类型转换进行适当的控制。
class ConvType
{
public:
ConvType(int i) {};
ConvType(char c) = delete; //删除char版本 不会生成char版本
};
void Func(ConvType ct)
{}
int main()
{
Func(3);
Func('a'); //无法通过编译
ConvType ci(3);
ConvType cc('a'); //无法通过编译
}
常量表达式 constexpr
静态数组的大小必须在编译期确定,所有报错
用constexpr 在编译期间size()会被确定,返回值为常量
Lambda函数
可以用它定义一个临时的函数对象,它像其它对象一样可以传递和保存。更为强大的是,它甚至可以访问当前函数的上下文。
Lambda函数实现优点:
- 代码简洁。无需另外定义函数或
class
即可实现。整体代码缩小了不少。 - 类型明确。新增的
std::function
是一个通用的函数对象,可以使用Lambda
初始化。最大的优点是参数和返回值都是明确的,可以从声明看出来。 - 无须使用模板。
可以访问上下文,如果10是一个变量
Lambda函数访问外部变量[]为捕获列表
捕获时机问题
注意局部变量