C++ / Syntax
现代 C++ 语法笔记(三)
整理原始字面量、long long、成员初始化、模板、异常等现代 C++ 语法点。
try-catch捕获异常
try块用于可能引发异常的代码,catch对异常进行捕获及处理
int main(){
try{
devide(10, 0);
}
catch(const char* e)
{
cout << "ERROR: " << e << endl;
}
return 0;
}
try中的代码称为保护代码,运行时可能抛出异常,然后异常会被catch接受,再进行处理
若有异常未能被捕获,程序会直接终止
try后可以跟很多个catch,抛出的异常会匹配对象类型相同且最近的catch,最后面可以加一个catch(...),接受任何类型的异常,防止有未被捕获的异常
栈展开:异常优先在当前函数栈中寻找匹配的catch,没有则退出到调用这层函数的栈,直到main函数,若依旧没找到则终止程序
自定义异常类:
class MyException{
MyException(string s):msg(s){}
string msg;
};
int devide(int a, int b)
{
if(b == 0)
{
throw MyException("devide by zero");
}
int result = a/b;
return result;
}
异常接口声明
使用throw()在函数声明是列出可能抛出的异常类型
int devide(int a, int b) throw(string, int) //函数只能抛出这两种类型的异常
{ //若违反此声明,有些编译器会给出警告,有些直接编译失败
if(b == 0)
{
throw "devide by zero";
}
int result = a/b;
return result;
}
- throw()修饰函数代表此函数不会抛出异常
- 不写throw()代表此函数可能抛出任何类型的异常
异常处理会给程序带来一些微小的性能开销
noexcept
throw(类型)声明在C++11中被弃用,throw()声明不抛出异常也被noexcept关键字代替
int devide(int a, int b) noexcept //此函数不会抛出异常
{
if(b == 0)
{
throw "devide by zero";
}
int result = a/b;
return result;
}
noexcept还可以接受一个常量表达式作为参数
type function() noexcept(常量表达式){}
常量表达式:
- 值为True,等于noexcept
- 值为False,表示可能抛出异常
自动类型推导
auto
auto:声明为auto类型的变量在编译时由编译器自动推导类型
注意:
- auto不是一种类型,而是类型声明的占位符
- 使用auto来声明的变量必须初始化,否则编译器无法推导
- 在下面的例子中,a与b的类型都是int\*,但声明a的auto被推导为int,和正常的声明一样,auto和\*要连在一起看,即为int*
int temp = 110;
auto *a = &temp;
auto b = &temp;
- 当变量不是指针或者引用类型时,推导的结果中不会保留const、volatile关键字
当变量是指针或者引用类型时,推导的结果中会保留const、volatile关键字
int tmp = 250;
const auto a1 = tmp;
auto a2 = a1;
const auto &a3 = tmp;
auto &a4 = a3;
此处a2不是const,a3,a4是const
不能使用auto的场景:
- 函数参数
- 类的除静态常量成员变量(可以在类内初始化)以外的成员变量,与声明时要初始化矛盾
- 数组
int array[] = {1,2,3,4,5};
auto t1 = array;
auto t2[] = array; //XXX
auto t3[] = {1,2,3,4,5}; //XXX
- 模板参数
Test<auto> t1 = t; //XXX
常用场景:
用于STL的容器遍历、泛型编程