프로그래밍/C++ 문법

Range-Based for Loops in C++

studylida 2023. 2. 22. 21:00

As a C++ programmer, you're likely familiar with the traditional for loop, which allows you to iterate over a sequence of elements in a container. However, C++11 introduced a new type of for loop that offers a more concise and expressive syntax for iterating over containers: the range-based for loop. In this article, we'll explore the basics of range-based for loops in C++, and show you how to use them to iterate over arrays, vectors, maps, and other container types.

What is a Range-Based For Loop?

A range-based for loop, also known as a for-each loop, is a type of for loop that enables you to iterate over a range of elements in a container. The syntax of a range-based for loop is as follows:

for (auto element : container) {
    // do something with element
}

The range-based for loop consists of three parts:

  1. The keyword for, followed by a pair of parentheses that enclose the loop's control variables.
  2. The loop control variable, which is declared using the auto keyword. This variable represents each element of the container as the loop iterates over it.
  3. The container, which is the range of elements that the loop will iterate over.

Compared to the traditional for loop, the range-based for loop has a simpler syntax that makes it easier to read and write code that iterates over container elements. Additionally, it is less error-prone than the traditional for loop, as it avoids issues with container bounds and index calculations.

Using Range-Based For Loops with Arrays

Let's start by looking at how to use range-based for loops with arrays. In C++, an array is a collection of elements of the same type, stored in contiguous memory locations. Here's an example of how to use a range-based for loop to iterate over an array of integers:

int arr[] = {1, 2, 3, 4, 5};
for (auto element : arr) {
    std::cout << element << " ";
}

In this example, we declare an array of integers and initialize it with five elements. We then use a range-based for loop to iterate over the elements of the array, printing each element to the console.

Using Range-Based For Loops with Vectors

Vectors are one of the most commonly used container types in C++. A vector is a sequence of elements of the same type that can grow or shrink dynamically. Here's an example of how to use a range-based for loop to iterate over a vector of strings:

std::vector<std::string> vec = {"apple", "banana", "orange"};
for (auto element : vec) {
    std::cout << element << " ";
}

In this example, we declare a vector of strings and initialize it with three elements. We then use a range-based for loop to iterate over the elements of the vector, printing each element to the console.

Using Range-Based For Loops with Maps

Maps are associative containers that store key-value pairs. Each key maps to a corresponding value, and keys must be unique. Here's an example of how to use a range-based for loop to iterate over a map of integers and strings:

std::map<int, std::string> mymap = {{1, "apple"}, {2, "banana"}, {3, "orange"}};
for (auto element : mymap) {
    std::cout << element.first << ": " << element.second << " ";
}

In this example, we declare a map that associates integer keys with string values. We then use a range-based for loop to iterate over the key-value pairs in the map, printing each key and value to the console. Note that the loop control variable is a pair of values, where the first element is the key and the second element is the value.

Using Range-Based Loops with User-Defined Types

Range-based loops can also be used with user-defined types, such as classes or structs. However, in order to do this, we need to define the necessary operators to allow the range-based loop to work. Here's an example of how to define the necessary operators to allow a range-based loop to work with a custom class:

#include <iostream>
#include <vector>

class MyClass {
public:
    MyClass(int x): _x(x) {}
    
    int getX() const { return _x; }
    
private:
    int _x;
};

class MyContainer {
public:
    MyContainer() {
        _vec.push_back(MyClass(1));
        _vec.push_back(MyClass(2));
        _vec.push_back(MyClass(3));
    }
    
    std::vector<MyClass>::const_iterator begin() const { return _vec.begin(); }
    std::vector<MyClass>::const_iterator end() const { return _vec.end(); }
    
private:
    std::vector<MyClass> _vec;
};

int main() {
    MyContainer container;
    
    for(auto& element: container) {
        std::cout << element.getX() << " ";
    }
    
    return 0;
}

By defining the begin() and end() operators, we can now use a range-based for loop to iterate over the elements of our custom container.

Modifying Elements with Range-Based For Loops

Range-based for loops not only allow us to read container elements but also to modify them. To modify the elements in a container, we need to use a reference to the loop control variable, as shown in the following example:

std::vector<int> vec = {1, 2, 3, 4, 5};
for (auto& element : vec) {
    element *= 2;
}

In this example, we declare a vector of integers and initialize it with five elements. We then use a range-based for loop to iterate over the elements of the vector and double each element by modifying it through a reference to the loop control variable. After the loop finishes, the vector will contain the elements {2, 4, 6, 8, 10}.

Using Const References with Range-Based For Loops

If we only need to read container elements and not modify them, we can use a const reference to the loop control variable. This is a good practice since it avoids accidental modifications to the container, making the code more robust. Here's an example of how to use a const reference with a range-based for loop:

std::vector<int> vec = {1, 2, 3, 4, 5};
for (const auto& element : vec) {
    std::cout << element << " ";
}

In this example, we declare a vector of integers and initialize it with five elements. We then use a range-based for loop with a const reference to iterate over the elements of the vector, printing each element to the console.

Range-Based For Loops vs Traditional For Loops

While range-based for loops offer a simpler and more expressive syntax for iterating over containers, there are situations where a traditional for loop may be more appropriate. For example, if we need to iterate over a container and access its elements using an index, or if we need to iterate over a sequence of elements that are not stored in a container, a traditional for loop may be the best option. However, in most cases where we need to iterate over a container and access its elements, a range-based for loop is the preferred choice due to its simplicity and reduced potential for errors.

'프로그래밍 > C++ 문법' 카테고리의 다른 글

Type Conversions in C++  (0) 2023.02.27
Operator Overloading in C++  (0) 2023.02.23
Object-Oriented Programming in C++  (0) 2023.02.20
Function Pointers in C++  (0) 2023.02.07
Dynamic Memory Allocation in C++  (0) 2023.02.06