1. 基于范围的 for 循环(C++11

1.1 范围 for 的语法

在 C++98 中如果要遍历一个数组,可以按照以下方式进行:

void TestFor() 
{ 
    int array[] = { 1, 2, 3, 4, 5 }; 
    for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)      
        array[i] *= 2; 
    
    for (int* p = array; p < array + sizeof(array)/ sizeof(array[0]); ++p)      
        cout << *p << endl; 
}

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此 C++11 中引入了基于范围的 for 循环。for 循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围

void TestFor() 
{ 
    int array[] = { 1, 2, 3, 4, 5 }; 
    for(auto& e : array)      
        e *= 2; 
    for(auto e : array)      
        cout << e << " "; 
    return 0; 
}

注意:与普通循环类似,可以用 continue 来结束本次循环,也可以用 break 来跳出整个循环

1.2 范围 for 的使用条件

1. for 循环迭代的范围必须是确定的

对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供 begin 和 end 的方法,begin 和 end 就是 for 循环迭代的范围。

注意:以下代码就有问题,因为 for 的范围不确定

void TestFor(int array[]) 
{     
    for(auto& e : array)         
    cout<< e <<endl; 
}

2. 迭代的对象要实现++和==的操作。(关于迭代器这个问题,以后会讲,现在提一下,没办法讲清楚,现在了解一下就可以了)

2. 指针空值 nullptr(C++11

2.1 C++98 中的指针空值

在良好的 C/C++编程习惯中,声明一个变量时最好给该变量一个合适的初始值,否则可能会出现不可预料的错误,比如未初始化的指针。如果一个指针没有合法的指向,我们基本都是按照如下方式对其进行初始化:

void TestPtr() 
{ 
    int* p1 = NULL; 
    int* p2 = 0; 
    // …… 
}

NULL 实际是一个宏,在传统的 C 头文件(stddef.h)中,可以看到如下代码:

#ifndef NULL 
#ifdef __cplusplus 
#define NULL   0 
#else 
#define NULL   ((void *)0) 
#endif 
#endif

可以看到,NULL 可能被定义为字面常量 0,或者被定义为无类型指针(void*)的常量。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如:

void f(int) 
{  
    cout<<"f(int)"<<endl; 
} 
void f(int*) 
{  
    cout<<"f(int*)"<<endl; 
} 
int main() 
{  
    f(0);  
    f(NULL);  
    f((int*)NULL); 
    
    return 0; 
}

程序本意是想通过 f(NULL)调用指针版本的 f(int*)函数,但是由于 NULL 被定义成 0,因此与程序的初衷相悖。

在 C++98 中,字面常量 0 既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void *)0。

注意:

1. 在使用 nullptr 表示指针空值时,不需要包含头文件,因为 nullptr 是 C++11 作为新关键字引入的

2. 在 C++11 中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。

3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用 nullptr。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐