Единицей выражения hc лямбда в си является
Обновлено: 04.11.2024
В C++ 11 и более поздних версиях лямбда-выражение, часто называемое лямбда– — это удобный способ определения объекта анонимной функции ( замыкания) непосредственно в расположении, где оно вызывается или передается в качестве аргумента функции. Обычно лямбда-выражения используются для инкапсуляции нескольких строк кода, передаваемых алгоритмам или асинхронным функциям. В этой статье определяются лямбда-выражения и их сравнение с другими методами программирования. Он описывает их преимущества и предоставляет некоторые основные примеры.
Похожие статьи
Части лямбда-выражения
В стандарте ISO C++ демонстрируется простое лямбда-выражение, передаваемое функции std::sort() в качестве третьего аргумента:
На следующем рисунке показана структура лямбда-выражения:
предложение Capture (также известное как оператор лямбда-выражения в спецификации C++).
список параметров Используемых. (Также называется лямбда-объявлением)
изменяемая спецификация Используемых.
Спецификация Exception Используемых.
замыкающий-возвращаемый тип Используемых.
Предложение Capture
Лямбда-выражение может добавлять новые переменные в тексте (в C++ 14), а также получать доступ к переменным из окружающей области или записывать их. Лямбда-выражение начинается с предложения Capture. Он указывает, какие переменные фиксируются, а также указывает, является ли запись по значению или по ссылке. Доступ к переменным с префиксом амперсанда ( & ) осуществляется по ссылке и к переменным, к которым нет доступа по значению.
Пустое предложение фиксации ( [ ] ) показывает, что тело лямбда-выражения не осуществляет доступ к переменным во внешней области видимости.
Можно использовать режим захвата по умолчанию, чтобы указать, как фиксировать все внешние переменные, упоминаемые в теле лямбда-выражения: означает, что [&] все переменные, на которые вы ссылаетесь, захватываются по ссылке, а [=] значит, они записываются по значению. Можно сначала использовать режим фиксации по умолчанию, а затем применить для определенных переменных другой режим. Например, если тело лямбда-выражения осуществляет доступ к внешней переменной total по ссылке, а к внешней переменной factor по значению, следующие предложения фиксации эквивалентны:
При использовании записи по умолчанию фиксируются только те переменные, которые упоминаются в теле лямбда-выражения.
Если предложение Capture включает запись-Default, то & ни один идентификатор в записи этого предложения записи не может иметь форму &identifier . Аналогично, если предложение Capture включает запись по умолчанию = , то ни один из этих предложений не может иметь форму =identifier . Идентификатор или this не может использоваться в предложении Capture более одного раза. В следующем фрагменте кода показаны некоторые примеры.
Захват, за которым следует многоточие, — это расширение пакета, как показано в следующем примере шаблона Variadic :
Чтобы использовать лямбда-выражения в теле функции члена класса, передайте this указатель в предложение Capture, чтобы предоставить доступ к функциям и членам данных включающего класса.
Visual Studio 2017 версии 15,3 и более поздних версий (доступно в /std: c++ 17): this указатель может быть захвачен значением путем указания *this в предложении capture. Захват по значению копирует весь замыкание на каждый узел вызова, где вызывается лямбда-выражение. (Замыканием является объект анонимной функции, инкапсулирующий лямбда-выражение.) Захват по значению полезен, когда лямбда выполняется в параллельных или асинхронных операциях. Это особенно полезно на некоторых аппаратных архитектурах, таких как NUMA.
Пример, демонстрирующий использование лямбда-выражений с функциями членов класса, см. в разделе "пример: использование лямбда-выражения в методе" в примерах лямбда-выражений.
При использовании предложения Capture рекомендуется учитывать такие моменты, особенно при использовании лямбда-выражений с многопоточностью:
Захваты ссылок можно использовать для изменения переменных вне, но захваты значений не могут. ( mutable позволяет изменять копии, но не оригиналы.)
Захват ссылок отражает обновления переменных вне, но не фиксирует значения.
Фиксация ссылки вводит зависимость от времени существования, тогда как фиксация значения не обладает зависимостями от времени существования. Это особенно важно при асинхронном выполнении лямбда-выражения. Если вы захватываете локальную по ссылке в асинхронном лямбда-выражении, это локально может быть легко пропала в момент выполнения лямбда-выражения. Код может вызвать нарушение прав доступа во время выполнения.
Обобщенная фиксация (C++14)
В C++14 вы можете объявлять и инициализировать новые переменные в предложении фиксации. Для этого не требуется, чтобы эти переменные существовали во внешней области видимости лямбда-функции. Инициализация может быть выражена в качестве любого произвольного выражения. Тип новой переменной определяется типом, который создается выражением. Эта функция позволяет собирать переменные только для перемещения (например, std::unique_ptr ) из окружающей области и использовать их в лямбда-выражении.
Список параметров
Лямбда-выражения могут записывать переменные и принимать входные параметры. Список параметров (лямбда-декларатор в стандартном синтаксисе) является необязательным и в большинстве аспектов напоминает список параметров для функции.
В C++ 14, если тип параметра является универсальным, можно использовать auto ключевое слово в качестве спецификатора типа. Это ключевое слово указывает компилятору создать оператор вызова функции в качестве шаблона. Каждый экземпляр auto в списке параметров эквивалентен отдельному параметру типа.
Лямбда-выражение может принимать другое лямбда-выражение в качестве своего аргумента. Дополнительные сведения см. в разделе «Лямбда-выражения более высокого порядка» в статье Примеры лямбда-выражений.
Поскольку список параметров является необязательным, можно опустить пустые скобки, если аргументы не передаются в лямбда-выражение и его лямбда-декларатор не содержит спецификацию Exception, завершающего-Return-Type или mutable .
Изменяемая спецификация
Как правило, оператор вызова функции лямбда-выражения является константой по значению, но использование mutable ключевого слова отменяет это. Он не создает изменяемых элементов данных. mutable Спецификация позволяет тексту лямбда-выражения изменять переменные, захваченные по значению. В некоторых примерах, приведенных далее в этой статье, показано, как использовать mutable .
Спецификация исключений
Можно использовать noexcept спецификацию исключения, чтобы указать, что лямбда-выражение не создает никаких исключений. Как и в случае с обычными функциями, компилятор Microsoft C++ создает предупреждение C4297 , если лямбда-выражение объявляет noexcept спецификацию исключения, а тело лямбда-выражения создает исключение, как показано ниже:
Дополнительные сведения см. в разделе спецификации исключений (throw).
Возвращаемый тип
Возвращаемый тип лямбда-выражения выводится автоматически. Не обязательно использовать auto ключевое слово, если не указан завершающий возвращаемый тип. Замыкающий возвращаемый тип напоминает часть функции, возвращающей возвращаемый тип, и функцию-член. Однако возвращаемый тип должен следовать за списком параметров -> . перед возвращаемым типом необходимо включить ключевое слово замыкающего возвращаемого типа.
Можно опустить часть возвращаемого типа лямбда-выражения, если тело лямбды содержит только один оператор return. Или, если выражение не возвращает значение. Если тело лямбда-выражения содержит один оператор return, компилятор выводит тип возвращаемого значения из типа возвращаемого выражения. В противном случае компилятор выводит тип возвращаемого значения как void . Рассмотрим следующие примеры фрагментов кода, иллюстрирующих этот принцип:
Лямбда-выражение может создавать другое лямбда-выражение в качестве своего возвращаемого значения. Дополнительные сведения см. в разделе "лямбда-выражения более высокого порядка" в примерах лямбда-выражений.
Тело лямбды
Тело лямбда-выражения является составным оператором. Он может содержать все, что разрешено в теле обычной функции или функции-члена. Тело обычной функции и лямбда-выражения может осуществлять доступ к следующим типам переменных:
Фиксированные переменные из внешней области видимости (см. выше).
Локально объявленные переменные.
Члены данных класса, объявленные внутри класса и this захваченные.
Любая переменная, имеющая статическую длительность хранения, например глобальные переменные.
В следующем примере содержится лямбда-выражение, которое явно фиксирует переменную n по значению и неявно фиксирует переменную m по ссылке.
Поскольку переменная n фиксируется по значению, ее значение после вызова лямбда-выражения остается равным 0 . mutable Спецификацию можно n изменить в лямбда-выражении.
Лямбда-выражение может записывать только переменные с автоматическим длительностью хранения. Однако можно использовать переменные со статической длительностью хранения в теле лямбда-выражения. В следующем примере функция generate и лямбда-выражение используются для присвоения значения каждому элементу объекта vector . Лямбда-выражение изменяет статическую переменную для получения значения следующего элемента.
Дополнительные сведения см. в разделе Generate.
В следующем примере кода используется функция из предыдущего примера и добавляется пример лямбда-выражения, использующего алгоритм стандартной библиотеки C++ generate_n . Это лямбда-выражение назначает элемент объекта vector сумме предыдущих двух элементов. mutable Ключевое слово используется, чтобы тело лямбда-выражения может изменить свои копии внешних переменных x и y , которое захватывает лямбда-выражение по значению. Поскольку лямбда-выражение захватывает исходные переменные x и y по значению, их значения остаются равными 1 после выполнения лямбда-выражения.
Дополнительные сведения см. в разделе generate_n.
constexpr лямбда-выражения
Visual Studio 2017 версии 15,3 и более поздних версий (доступно в /std:c++17 ): лямбда-выражение можно объявить как constexpr (или использовать его в константном выражении), если инициализация каждого захваченного или введенного элемента данных разрешена в константном выражении.
Лямбда-выражение неявно, constexpr если его результат удовлетворяет требованиям constexpr функции:
Если лямбда-выражение неявно или неявное constexpr , то преобразование в указатель функции создает constexpr функцию:
Специально для систем Майкрософт
Лямбда-выражения не поддерживаются в следующих управляемых сущностях среды CLR: ref class , ref struct , value class или value struct .
Если вы используете модификатор, зависящий от Майкрософт __declspec , например, его можно вставить в лямбда-выражение сразу после parameter-declaration-clause . Пример:
Чтобы определить, поддерживается ли определенный модификатор лямбда-выражениями, см. статью об модификаторе в разделе модификаторы, относящиеся к Microsoft .
Visual Studio поддерживает стандартную лямбда-функцию c++ 11 и лямбда-выражения без отслеживания состояния. Лямбда без отслеживания состояния преобразуется в указатель функции, который использует произвольное соглашение о вызовах.
Читайте также: