Chuyển tới nội dung chính

std::for_each

#include <algorithm>

// C++98/C++03
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);

// C++11 trở lên
template <class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);

Áp dụng một hàm (hoặc đối tượng hàm) cho mỗi phần tử trong một phạm vi (range) được chỉ định. Nó cho phép bạn thực hiện một hành động cụ thể trên từng phần tử mà không cần viết vòng lặp thủ công.

Tham số

first

  • Input Iterator trỏ đến phần tử đầu tiên trong phạm vi cần xử lý.

last

  • Input Iterator trỏ đến phần tử ngay sau phần tử cuối cùng trong phạm vi cần xử lý. Phạm vi bao gồm từ first đến last nhưng không bao gồm last ([first, last)).

f

  • Hàm hoặc đối tượng hàm được áp dụng cho mỗi phần tử trong phạm vi.
    • UnaryFunction (C++98/C++03): Phải là một hàm hoặc đối tượng hàm nhận một đối số (là giá trị của phần tử) và không trả về giá trị (void).
    • Function (C++11 trở lên): Linh hoạt hơn, có thể nhận một đối số (hoặc nhiều hơn, nếu bạn dùng std::bind hoặc lambda) và có thể trả về giá trị (giá trị trả về sẽ bị bỏ qua).

Giá trị trả về

  • Phiên bản C++98/C++03: Trả về chính hàm hoặc đối tượng hàm f đã được truyền vào (ít hữu dụng).
  • Phiên bản C++11 trở lên: Trả về hàm hoặc đối tượng hàm f sau khi đã được áp dụng cho tất cả các phần tử trong phạm vi. Điều này cho phép thay đổi trạng thái bên trong của đối tượng hàm f (nếu có) và truy cập nó sau khi for_each() kết thúc.

Đặc điểm

  1. for_each() duyệt qua các phần tử theo thứ tự từ first đến last.
  2. Trong C++11 trở lên, bạn thường nên sử dụng range-based for loop thay cho for_each() vì cú pháp ngắn gọn và dễ đọc hơn:
    for (int& i : numbers) {
    i *= 2;
    }
  3. Tuy nhiên, for_each() vẫn hữu ích trong một số trường hợp, chẳng hạn như khi bạn muốn sử dụng lại một đối tượng hàm có trạng thái, hoặc khi bạn muốn làm việc với các iterator phức tạp hơn.
  4. for_each() thường được sử dụng để thực hiện các thao tác đơn giản trên mỗi phần tử trong một container như:
    • In giá trị các phần tử ra màn hình.
    • Thay đổi giá trị các phần tử (ví dụ: tăng mỗi phần tử lên 1 đơn vị).
    • Tính tổng, tích, hoặc các giá trị thống kê khác từ các phần tử.

Ví dụ

#include <iostream>
#include <vector>
#include <algorithm>

// Hàm in giá trị phần tử
void printElement(int i) {
std::cout << i << " ";
}

// Đối tượng hàm để tính tổng
class SumCalculator {
public:
SumCalculator() : sum(0) {}
void operator()(int i) { sum += i; }
int getSum() const { return sum; }

private:
int sum;
};

int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};

// Sử dụng con trỏ hàm để in các phần tử
std::cout << "Elements: ";
std::for_each(numbers.begin(), numbers.end(), printElement);
std::cout << std::endl;

// Sử dụng biểu thức lambda để nhân đôi mỗi phần tử
std::for_each(numbers.begin(), numbers.end(), [](int& i){ i *= 2; });

// In lại các phần tử sau khi nhân đôi
std::cout << "Doubled elements: ";
std::for_each(numbers.begin(), numbers.end(), printElement);
std::cout << std::endl;

// Sử dụng đối tượng hàm để tính tổng
SumCalculator sumCalculator;
sumCalculator = std::for_each(numbers.begin(), numbers.end(), sumCalculator); // C++11
std::cout << "Sum: " << sumCalculator.getSum() << std::endl;

return 0;
}

Các hàm liên quan

transformÁp dụng một hàm (hoặc đối tượng hàm) cho mỗi phần tử trong một phạm vi (range) đầu vào và lưu trữ kết quả vào một phạm vi đầu ra
findTìm kiếm phần tử đầu tiên trong một phạm vi có giá trị bằng với một giá trị cho trước
searchTìm kiếm sự xuất hiện đầu tiên của một dãy con trong một phạm vi lớn hơn