TGViewer
Библиотека C/C++ разработчика | cpp, boost, qt Библиотека C/C++ разработчика | cpp, boost, qt @cppproglib · 16.9K subscribers
Post #6595 2.08K
🍙 C++ Ranges. Ленивые вычисления (C++20)
Cамое важное свойство адаптеров views: они ленивые (lazy).


Когда ты пишешь data | views::filter(...) | views::transform(...), ты не запускаешь обработку. Ты создаёшь лёгкий view-объект, который хранит ссылку на исходный диапазон и предикаты. Обработка происходит только тогда, когда ты начинаешь итерировать результат — поэлементно, по требованию.

⚠️ Важно: view хранит ссылку на исходный контейнер. Если контейнер изменится или выйдет из области видимости раньше, чем ты начнёшь итерацию — поведение будет неопределённым.


🌸 Пример 1: базовая ленивость
// C++20
#include <vector>
#include <ranges>
#include <iostream>

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

// Создаём view — никакой обработки ещё нет
auto view = v | std::views::filter([](int x) {
std::cout << "Проверяем " << x << "\n";
return x > 2;
});

std::cout << "Начинаем итерацию:\n";
for (int x : view) {
std::cout << "Результат: " << x << "\n";
}
}


❗️Вывод — фильтрация и результат чередуются поэлементно. Это и есть ленивость в действии:

Начинаем итерацию:
Проверяем 1
Проверяем 2
Проверяем 3
Результат: 3
Проверяем 4
Результат: 4
Проверяем 5
Результат: 5


Сравни с тем, как выглядел бы «жадный» (eager) подход: сначала все "Проверяем...", потом все "Результат:". Здесь же — один элемент за раз.

🌱 Пример 2: цепочка адаптеров

Можно выстраивать цепочки — каждый адаптер обрабатывает элемент по мере продвижения итератора:

#include <vector>
#include <ranges>
#include <iostream>

int main() {
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

auto view = v
| std::views::filter([](int x) { return x % 2 == 0; }) // только чётные
| std::views::transform([](int x) { return x * x; }); // возводим в квадрат

for (int x : view) {
std::cout << x << " "; // 4 16 36 64 100
}
}


Здесь transform никогда не видит нечётных чисел — filter не пропускает их дальше. Никаких промежуточных векторов, никаких лишних аллокаций.


🌳 Пример 3: ранняя остановка

Ленивость особенно выгодна, когда тебе не нужны все элементы. views::take берёт ровно столько, сколько нужно, и останавливает обработку:

#include <vector>
#include <ranges>
#include <iostream>

int main() {
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// Берём первые 3 чётных числа — и всё, остальные даже не проверяются
auto view = v
| std::views::filter([](int x) {
std::cout << "Проверяем " << x << "\n";
return x % 2 == 0;
})
| std::views::take(3);

for (int x : view) {
std::cout << "Берём: " << x << "\n";
}
}


Вывод:
Проверяем 1
Проверяем 2
Берём: 2
Проверяем 3
Проверяем 4
Берём: 4
Проверяем 5
Проверяем 6
Берём: 6
Проверяем 7 // Могут быть проверены (зависит от компилятора)
Проверяем 8 // хотя это не обязательно


После шестёрки обработка полностью прекращается. Числа 7–10 не тронуты — хотя они есть в векторе.


💡 Итоги

Ленивость — это не просто деталь реализации. Это архитектурное свойство, которое позволяет:

• работать с бесконечными диапазонами (std::views::iota)
• не создавать промежуточные контейнеры при цепочках
• останавливать обработку раньше, как только результат получен

Плата за это — view не кэширует результаты. Если ты итерируешь view дважды, предикаты выполнятся дважды. Если это проблема — преврати результат в вектор через std::ranges::to<std::vector>() (C++23) или просто std::vector(view.begin(), view.end()).


🐸 Продолжение следует...


📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#константная_правильность
  • 🔥 8
  • 👍 3
  • ❤ 2
More from @cppproglib
  1. Sep 19, 2026А вы уже забрали свой подарок ко Дню программиста? К вашему профессиональному празднику Tp…
  2. Sep 18, 2026От исходного кода до процессора: разберись, как работает программа 💻 Стартует практически…
  3. Sep 15, 2026😭 Как не потратить недельный лимит AI-кодинга за три дня? Разберём на вебинаре, как трати…
  4. Sep 13, 2026🤪 Если бы можно было задать один вопрос про AI в разработке — что бы вы спросили? Как выб…
  5. Sep 13, 2026🤩 Inline static в классах — забудь про .cpp Сколько раз ты забывал добавить определение s…
  6. Sep 13, 2026🌸 Вселенная намекает: пора уже начать этот курс С 14 сентября цены в Proglib Academy выра…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →