Лямбда-вирази в c
Лямбда-вираз (або просто лямбда) в C ++ 11 - це зручний спосіб визначення анонімного об'єкта функції безпосередньо в місці його виклику або передачі в функцію як аргумент. Зазвичай лямбда-вирази використовуються для інкапсуляції декількох рядків коду, що передаються алгоритмам або асинхронним методам. У цій статті наводиться визначення лямбда-виразів, їх порівняння з іншими методами програмування, опис їх переваг і простий приклад.
У стандарті ISO C ++ демонструється просте лямбда-вираз, що передається функції std :: sort () в якості третьої аргументу:
На наступному малюнку показана структура лямбда-вирази:

пропозиція фіксації (в специфікації C ++ це lambda-introducer.)
список параметрів (необов'язково). (Також іменується як lambda declarator.)
відключається специфікація (необов'язково).
специфікація винятків (необов'язково).
завершальний повертається тип (необов'язково).
пропозиція фіксації
У тілі лямбда-вирази можуть вводитися нові змінні (в C ++ 14). Крім того, лямбда-вирази можуть використовувати, або фіксувати. змінні з навколишнього області видимості. Лямбда-вираз починається з пропозиції фіксації (в синтаксисі стандарту - lambda-introducer), в якому зазначаються фіксуються змінні, а також спосіб фіксації: за значенням або за посиланням. Доступ до змінних з префіксом з амперсандом ( ) Здійснюється за посиланням, а до змінних без префікса - за значенням.
Пусте пропозицію фіксації ([]) показує, що тіло лямбда-вирази не здійснює доступ до змінних у зовнішній області видимості.
Щоб задати спосіб фіксації зовнішніх змінних, на які посилається лямбда-вираз, ви можете використовувати режим фіксації за замовчуванням (в синтаксисі стандарту - capture-default): [] - всі змінні фіксуються за посиланням, [=] - за значенням. Можна спочатку використовувати режим фіксації за замовчуванням, а потім застосувати для певних змінних інший режим. Наприклад, якщо тіло лямбда-вирази здійснює доступ до зовнішньої змінної total по посиланню, а до зовнішньої змінної factor за значенням, такі пропозиції фіксації еквівалентні:
Щоб використовувати лямбда-вирази в тілі методу класу, необхідно передати покажчик this пропозицією фіксації, щоб забезпечити доступ до методів і даними-членам включає класу. Приклад використання лямбда-виразів з методами класів см. В розділі Приклади лямбда-виразів (підрозділ "Використання лямбда-вирази в методі").
При використанні пропозиції фіксації рекомендується пам'ятати про ці важливі аспекти, особливо при використанні лямбда-виразів з багатопоточність:
Фіксацію посилань можна використовувати для зміни змінних зовні, тоді як фіксацію значень не можна. (Mutable дозволяє змінювати копії, але не оригінали.)
Фіксація посилань відображає зміну змінних зовні, тоді як фіксація значень - немає.
Фіксація посилання вводить залежність від часу існування, тоді як фіксація значення не має залежностями від часу існування. Це особливо важливо в разі асинхронного використання лямбда-виразів. Якщо в асинхронному лямбда-виразі за посиланням фіксується локальна змінна, цілком ймовірно, що до моменту його виклику вона стане недоступною, що викличе виключення порушення прав доступу під час виконання.
Узагальнена фіксація (C ++ 14)
У C ++ 14 ви можете оголошувати і ініціалізувати нові змінні в реченні фіксації. Для цього не потрібно, щоб ці змінні існували у зовнішній області видимості лямбда-функції. Ініціалізація може бути виражена як будь-якого довільного виразу. Тип нової змінної визначається типом, який створюється виразом. Одна з переваг цієї можливості полягає в тому, що в C ++ 14 таким чином можна фіксувати змінні з навколишнього області видимості, доступні тільки для переміщення (наприклад std :: unique_ptr), і використовувати їх в лямбда-виразі.
Лямбда-вираз може створювати інше лямбда-вираз в якості свого значення, що повертається. Додаткові відомості див. У розділі Приклади лямбда-виразів (підрозділ "Лямбда-вирази вищого порядку").
Тіло лямбда-вирази
Частина лямбда-вирази, що містить його тіло (compound-statement в синтаксисі стандарту), може містити ті ж елементи, що і тіло звичайного методу або функції. Тіло звичайної функції і лямбда-вирази може здійснювати доступ до наступних типів змінних:
Фіксовані змінні із зовнішнього області видимості (див. Вище).
Локально оголошені змінні
Будь-яка змінна, яка має статичну тривалість зберігання (наприклад, глобальна змінна)
У наступному прикладі міститься лямбда-вираз, яке явно фіксує зміну n за значенням і неявно фіксує зміну m по посиланню.
5
0 Оскільки змінна n фіксується за значенням, її значення після виклику лямбда-вирази залишається рівним 0. Специфікація mutable дозволяє змінювати n всередині лямбда-вирази.
Незважаючи на те що лямбда-вираз може фіксувати тільки змінні з автоматичною тривалістю зберігання, в тілі лямбда-вирази можна використовувати змінні, які мають статичну тривалість зберігання. У наступному прикладі функція generate і лямбда-вираз використовуються для присвоєння значення кожного елементу об'єкту vector. Лямбда-вираз змінює статичну змінну для отримання значення наступного елемента.
Visual Studio підтримує синтаксис і функції лямбда-виразів стандарту C ++ 11 з наступними виключеннями:
Як і всі інші класи, лямбда-вирази не отримують автоматично створені конструктори переміщення і оператори присвоювання з переміщенням. Додаткові відомості про підтримку посилань rvalue см. В розділі Підтримка можливостей C ++ 11/14/17 (підрозділ "Посилання rvalue").
Необов'язковий параметр attribute-specifier-seq не підтримуються в цій версії.
Visual Studio включає наступні функції на додаток до функцій лямбда-виразів стандарту C ++ 11:
Що не мають станів лямбда-вирази є універсально перетворюваними в покажчики функцій з довільними угодами про виклики.
Автоматично виведені повертаються типи для тіла лямбда-виразів, які складніше, ніж