1.switch中case最好加{}
目的:防止跨过变量的初始化语句(包括隐式和显示)直接跳转到该变量作用于内的另一个位置。
case加{}:在该case中定义的变量,有效范围为该case;
case不加{}:在该case中定义的变量,有效范围是switch;
错误案例:
case 1://假设控制流绕过了该case
string file_name;//错误:控制流绕过一个隐式的初始化变量
int ival = 0; //错误:控制流绕过一个显示的初始化变量
int jval; //正确:该变量没有初始化
break;
case 2:
jval = next_num(); //正确:给jval赋一个值
if(file_name.empty()){} //file_name在作用于中,但是没有初始化
break;
假设上述代码合法,则一旦控制流直接跳到分支2,也就同时略过了变量file_name和ival的初始化过程。
此时这两个变量为作用于之内,跟在分支2中的代码试图在尚未初始化的情况下使用他们,这显然是行不通的。
解决方案:如果某个case要定义并初始化一个变量,我们应该保证该变量在块内,防止其他case引用该变量。注意break在{}之外!
正确案例:
case 1:
{
string file_name = get_file_name();
}
break;//注意break在{}之外!!!!!!!!
case 2:
if(file_name.empty()){}//错误:file_name不在作用于之内
2. 范围for语句
形式:for (declaration : expression) { statement}
注意事项:
- expression必须是一个序列:数组、vector或者string等包含begin()和end()的
- 每次迭代都会重新定义一个循环控制变量
- 范围for中预存了end(),一旦序列中添加(删除)元素,end()函数可能就变得无效
vector<int> v = {0,1,2,3,4,5};
for(auto &r : v){//这里循环变量用的是引用,只有这样才能对元素执行修改操作
r += 2;
}