2015-07-18 1 views
9

Я ткнулся вокруг шаблона Visual Studio для приложения DirectX. Я наткнулся на линию m_time.Tick([&]() { ... });, и я не могу понять, что означает часть [&](). Я даже не уверен, что это глупый вопрос, потому что я довольно неопытен в C++.Что означает код `[&]()` в C++?

Я знаю, что [] используется для выражения лямбда, но я не уверен, что имеет смысл. Может быть, какой-то странный делегат идиомы? Я даже не знаю. Если вы можете указать мне в сторону списка других неясных идиом, которые я мог бы встретить, пытаясь изучить C++, я был бы очень признателен.

+5

Это синтаксис функции [лямбда-функции] (http://en.cppreference.com/w/cpp/language/ лямбда). – Cameron

+0

@Cameron: эта ссылка идеальна. Является ли это слишком очевидным вопросом для полного ответа? Я хочу, чтобы вы повысили его за счет того, что вы, вероятно, спасли меня через несколько часов, выяснив, как google "[&}() {" – postitman

+0

Описание Lambda: http://stackoverflow.com/questions/7627098/what-is-a- lambda-expression-in-c11 –

ответ

8

Это пример lambda function.

C++ полон неясных углов, но по мере того как нечетный синтаксис идет, функции лямбда хорошо изучают. Основной синтаксис для объявления лямбда-функции - []() { }. Это выражение, которое приводит к объекту определенного для реализации типа, который может быть вызван, как если бы он был функцией (поскольку где-то в реализации компилятора синтаксиса лямбда-выражения это - a функция).

Первое преимущество, которое это дает, заключается в том, что функция может быть объявлена ​​встроенной с остальной частью кода вместо того, чтобы быть объявленной отдельно (что часто неудобно для очень коротких или специальных функций).

Самая мощная часть лямбда-выражений, однако, является их способность захвата переменных из окружающего контекста: Это то, что делает & в примере кода. Лямбда, объявленная с [&], фиксирует все переменные (и неявный указатель this, если используется внутри метода) по ссылке. (Там же [=] захватить по значению, и даже расширенный синтаксис, чтобы захватить только определенные переменные определенным образом.)

Короче говоря, этот код:

m_time.Tick([&]() { ... }); 

вызывает Tick метод на m_time объекта, и передает ему лямбда-функцию, которая захватывает окружающий контекст посредством ссылки. Предположительно, тогда метод Tick вызывает эту лямбда-функцию во время ее выполнения. В пределах ... могут быть использованы переменные, доступные в области, в которой была объявлена ​​лямбда, и эта способность захвата является самой мощной и удобной функцией лямбда.

1

Выражение лямбда определяет анонимную функцию, которая может захватывать вещи из сферы ее определения. В частности, [&] означает, что он фиксирует все автоматические переменные по ссылке, а () означает, что он не принимает аргументов. Что следует в `{...} - это тело функции. См. http://en.cppreference.com/w/cpp/language/lambda для получения дополнительной информации о лямбда.

Предположительно, Tick ожидает, что его параметр будет вызываемым объектом; лямбда служит этой цели и ее легко определить. Объект, который определяет оператор вызова, вероятно, будет работать и в этом контексте. Так может быть указатель функции.

+1

Лямбда не является функцией. Это * выражение *. –

2

Это выражение лямбда. Это довольно типичное выражение. Часть в скобках - это предложение захвата лямбда и означает, как она взаимодействует с локальными переменными в охватывающей области. Скобки будут содержать список параметров, как функцию, а затем в скобках - определение функции.

Вот хорошая запись, которая не слишком эзотерична. http://www.drdobbs.com/cpp/lambdas-in-c11/240168241

1

От C++ Primer

[&] неявного список ссылки захвата. Сущности из функции ограждающей, используемой в теле лямбда используются ссылки

Так практически, думать о выражении [&]() {...} как заявление, выражающее, что вы хотите ссылки на все переменные, объявленные в охватывающей области, чтобы быть доступны в лямбда-выражения. Например ...

#include <iostream> 

int main(int argc, char** argv) { 
    int x = 0; 
    int y = 1; 

    auto f1 = [&]() { std::cout << x << std::endl; } 

    auto f2 = [&x]() { std::cout << x << std::endl; } 

    auto f3 = [x]() { std::cout << x << std::endl; } 

    ++x; 

    f1(); 
    f2(); 
    f3(); 
} 
  • f1 напечатает 1
  • f2 напечатает 1
  • f3 напечатает 0

Разница betwee f1 и f2 в том, что f1 захватывает ссылку как x, так и y, тогда как f2 фиксирует ссылку только на x. С другой стороны, f3 фиксирует значение x (в данном случае 0) во время определения. Так как оба, f1 и f2 фиксируют ссылку на x, они будут печатать 1 при вызове после того, как x будет увеличен. Однако, поскольку f3 зафиксировал значение x во время определения, f3 будет печатать 0.

Смежные вопросы