C++11
基于范围的for循环
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
for (int & e: a)
{
e *= 2;
}
for (int & e: a)
{
cout << e << ", ";
}
cout << endl;
return 0;
}
使用基于范围的for循环,其for循环迭代的范围必须是可确定的:
int func(int a[])//形参中数组是指针变量,无法确定元素个数
{
for(auto e: a) // err, 编译失败
{
cout << e;
}
}
int main()
{
int a[] = {1, 2, 3, 4, 5};
func(a);
return 0;
}
静态断言
C/C++提供了调试工具assert,这是一个宏,用于在运行阶段对断言进行检查,如果条件为真,执行程序,否则调用abort()。
int main()
{
bool flag = false;
//如果条件为真,程序正常执行,如果为假,终止程序,提示错误
assert(flag == true); //#include <cassert>或#include <assert.h>
cout << "Hello World!" << endl;
return 0;
}
int main()
{
//该static_assert用来确保编译仅在32位的平台上进行,不支持64位的平台
static_assert( sizeof(void *)== 4, "64-bit code generation is not supported.");
cout << "Hello World!" << endl;
return 0;
}
noexcept修饰符
void func3() throw(int, char) //只能够抛出 int 和char类型的异常
{//C++11已经弃用这个声明
throw 0;
}
void BlockThrow() throw() //代表此函数不能抛出异常,如果抛出,就会异常
{
throw 1;
}
//代表此函数不能抛出异常,如果抛出,就会异常
//C++11 使用noexcept替代throw()
void BlockThrowPro() noexcept
{
throw 2;
}
nullptr
nullptr是为了解决原来C++中NULL的二义性问题而引进的一种新的类型,因为NULL实际上代表的是0
void func(int a)
{
cout << __LINE__ << " a = " << a <<endl;
}
void func(int *p)
{
cout << __LINE__ << " p = " << p <<endl;
}
int main()
{
int *p1 = nullptr;
int *p2 = NULL;
if(p1 == p2)
{
cout << "equal\n";
}
//int a = nullptr; //err, 编译失败,nullptr不能转型为int
func(0); //调用func(int), 就算写NULL,也是调用这个
func(nullptr);
return 0;
}
强类型枚举
C++ 11引入了一种新的枚举类型,即“枚举类”,又称“强类型枚举”。声明请类型枚举非常简单,只需要在enum后加上使用class或struct。如:
enum Old{Yes, No}; // old style
enum class New{Yes, No}; // new style
enum struct New2{Yes, No}; // new style
“传统”的C++枚举类型有一些缺点:它会在一个代码区间中抛出枚举类型成员(如果在相同的代码域中的两个枚举类型具有相同名字的枚举成员,这会导致命名冲突),它们会被隐式转换为整型,并且不可以指定枚举的底层数据类型。
int main()
{
enum Status{Ok, Error};
//enum Status2{Ok, Error};//err, 导致命名冲突, Status已经有成员叫Ok, Error
return 0;
}
在C++11中,强类型枚举解决了这些问题:
int main()
{
enum class Status {Ok, Error};
enum struct Status2 {Ok, Error};
//Status flag2 = Ok; // err,必须使用强类型名称
Status flag3 = Status::Ok;
enum class C : char { C1 = 1, C2 = 2};//指定枚举的底层数据类型
enum class D : unsigned int { D1 = 1, D2 = 2, Dbig = 0xFFFFFFF0U };
cout << sizeof(C::C1) << endl; // 1
cout << sizeof(D::D1) << endl; // 4
cout << sizeof(D::Dbig) << endl; // 4
return 0;
}
常量表达式
常量表达式主要是允许一些计算发生在编译时,即发生在代码编译而不是运行的时候。
这是很大的优化:假如有些事情可以在编译时做,它将只做一次,而不是每次程序运行时都计算。
使用constexpr,你可以创建一个编译时的函数:
constexpr int GetConst()
{
return 3;
}
int main()
{
int arr[ GetConst() ] = {0};
enum { e1 = GetConst(), e2 };
constexpr int num = GetConst();
return 0;
}
constexpr函数的限制:
- 函数中只能有一个return语句(有极少特例)
- 函数必须返回值(不能是void函数)
- 在使用前必须已有定义
- return返回语句表达式中不能使用非常量表达式的函数、全局数据,且必须是一个常量表达式
//err,函数中只能有一个return语句
constexpr int data()
{
constexpr int i = 1;
return i;
}
constexpr int data2()
{
//一个constexpr函数,只允许包含一行可执行代码
//但允许包含typedef、 using 指令、静态断言等。
static_assert(1, "fail");
return 100;
}
int a = 3;
constexpr int data3()
{
return a;//err, return返回语句表达式中不能使用非常量表达式的函数、全局数据
}
int main()
{
constexpr int func(); //函数声明,定义放在main函数后面
constexpr int c = func(); //err, 无法通过编译, 在使用前必须已有定义
return 0;
}
constexpr int func()
{
return 1;
}