C++11范围for详解

    技术2022-07-10  84

    这里写自定义目录标题

    作用使用方法例子使用范围for来修改字符串的值为什么要用引用 范围for与常规for循环语句比较使自己定义的容器类型支持范围循环

    作用

    C++ 11提供了一个特殊版本的 for 循环,在很多情况下,它都可以简化数组的处理,这就是基于范围的 for 循环。在使用基于范围的 for 循环处理数组时,该循环可以自动为数组中的每个元素迭代一次。

    使用方法

    如果对一个 8 元素的数组使用基于范围的 for 循环,则该循环将迭代 8 次。因为基于范围的 for 循环可以自动知道数组中元素的个数,所以不必使用计数器变量控制其迭代,也不必担心数组下标越界的问题。

    基于范围的 for 循环使用了一个称为范围变量的内置变量。每次基于范围的 for 循环迭代时,它都会复制下一个数组元素到范围变量。例如,第一次循环迭代,范围变量将包含元素 0 的值;第二次循环迭代,范围变量将包含元素 1 的值,以此类推。

    以下是基于范围的 for 循环的一般格式:

    for (dataType rangeVariable : array) statement;

    该格式的各个部分的含义: dataType:是范围变量的数据类型。它必须与数组元素的数据类型一样,或者是数组元素可以自动转换过来的类型。 rangeVariable:是范围变量的名称。该变量将在循环迭代期间接收不同数组元素的值。在第一次循环迭代期间,它接收的是第一个元素的值;在第二次循环迭代期间,它接收的是第二个元素的值;以此类推。 array:是要让该循环进行处理的数组的名称。该循环将对数组中的每个元素迭代一次。 statement:是在每次循环迭代期间要执行的语句。要在循环中执行更多的语句,则可以使用一组大括号来包围多个语句。

    例子

    假设定义了如下数组:

    int addr[] = {1,2,3,4,5};

    那么根据上面的语法格式,要想遍历整个数组,就可以使用如下方法:

    for(int value : numbers) { cout << value<<" " ; cout << endl; }

    数组addr有五个元素,第一次迭代时,value的值就是addr[0]的值,第二次迭代时就接收addr[1]中的值,以此类推,直到访问完所有元素。 那么上面代码的输出将会是:

    1 2 3 4 5

    还可以使用auto关键字来指定范围变量的数据类型:

    for(auto value : numbers) { cout << value << " "; cout << endl; }

    以下代码使用范围for来输出string变量的元素:

    #include<iostream> #include<string> using namespace std; int main() { string str = "abcdef"; cout << "Here is the output of the range for" << endl; for (char value : str){ cout << value << " "; } cout << endl; return 0; }

    程序的输出也是将string变量的值依次输出:

    使用范围for来修改字符串的值

    当范围 for 循环执行时,其范围变量将仅包含一个数组元素的副本。因此,不能使用基于范围的 for 循环来修改数组的内容,除非将范围变量声明为一个引用。引用变量是其他值的一个别名,任何对于引用变量的修改都将实际作用于别名所代表的值。

    #include<iostream> #include<string> using namespace std; int main() { string str = "abcdef"; for (char &val : str) { cin >> val; } cout << "\nHere are the values you entered: \n"; for (char val : str) cout << val << " "; cout << endl; return 0; }

    为什么要用引用

    (1):当传入的迭代参数类型为非引用时,做的是值传递,值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值,所以才修改无效。 (2)而在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量,所以修改有效。

    范围for与常规for循环语句比较

    基于范围的 for 循环可用于需要遍历数组所有元素的任何情形,并且不需要使用元素下标。但是,如果出于某些目的需要使用元素下标时,基于范围的 for 循环就不能使用了。另外,如果循环控制变量被用于访问两个或两个以上不同数组的元素,那么它也不适合使用。在这些情况下,可以使用常规 for 循环。

    使自己定义的容器类型支持范围循环

    一个类只要提供了分别获取起始和终止迭代器的begin和end函数,以及++ && – &&== && != 操作,就可以支持基于范围的for循环 一下实例代码为转载:

    #include "stdafx.h" #include <iostream> using namespace std; template <typename T, size_t S> class Array { public: T &operator[](size_t i) { return m_array[i]; } T const &operator[](size_t i)const { return const_cast<Array&>(*this)[i]; } //获取起始迭代器 T *begin() { return m_array; } T const *begin()const { return const_cast<Array *>(this)->begin(); } //获取终止迭代器 T *end() { return m_array + S; } T const *end()const { return const_cast<Array *>(this)->end(); } private: T m_array[S]; }; int main() { int i = 0; Array<int, 5> ai; for (auto &a : ai) a = ++i * 10; auto const &cai = ai; for (auto &a : cai) cout << /*++*/a << " "; cout << endl; return 0; }
    Processed: 0.029, SQL: 9