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 2if(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;
}