2015-10-01 3 views
3

Я просто написал довольно большой захват:Lambda влияние на производительность функции захвата

[this, &newIndex, &indexedDirs, &filters, &flags, &indexRecursion](){... 

Я использую это лямбда (indexRecursion) для рекурсии с thoudands элементов и спросил себя, если это будет более эффективно использовать «глобальный» захват [&]. Поскольку я не имею понятия об осуществлении захвата, мне нужно некоторое объяснение. Пожалуйста, с фоном тоже.

+6

осуществление определено. нет правильного ответа. если производительность является проблемой, переосмыслите алгоритм. –

+1

'&' вероятно, имеет тот же эффект, что и явный захват всего, что вы на самом деле используете, поэтому оно не будет быстрее. – Brian

+0

Обратите внимание, что с глобальным захватом '[&]' вы будете захватывать 'this' по ссылке и потенциально вводит другое косвенное направление. – Jarod42

ответ

3

Обычно вы можете думать о лямбда как эквивалент этого:

class ANON { 
    int data; 
    public: 
    void operator()(void) const { 
     cout << data << endl; 
    } 
} lambda; 
// auto lambda = [data]() {cout << data << endl;} 

Это должно дать вам представление о том, как осуществляется захват. Захват всех (будь то копией = или ссылкой &), вероятно, будет не более чем синтаксическим сахаром для указания всех используемых/доступных переменных для захвата в текущей области.

Но с тех пор ...

[..] Реализация может определить тип закрытия отличается от того, что описано ниже, если это не изменяет наблюдаемого поведения программы, кроме путем изменения: [. .] размер и/или выравнивание типа закрытия [..]

[N4431 §5.1.2/3]

... это было бы законно реализация использовать какой-то «черная магия» для захвата всеми ссылочными лямбдами и просто использовать указатель на захваченный кадр стеки, переписывание доступы к переменным, как доступу к некоторому смещению этого указателя:

class ANON { 
    void * stack_frame; 
    public: 
    void operator()(void) const { 
     cout << *static_cast<int *>(stack_frame + 8) << endl; 
    } 
} lambda; 

Так, используя &мощи (некоторый день) быть более эффективными, но, как уже сказал, что это реализация определена, и на это не на что положиться.

2

Внутренние lambdas обычно выполняются как специальные классы, один экземпляр которых сконструирован в точке лямбда-определения и которые вызывают функтор, который будет вызываться позже. Таким образом, производительность лямбда следует сравнивать с передачей метода функции с использованием std::bind.

Захваты не являются мистическими сущностями. Если захваты являются привязками привязки, объекты, к которым они относятся, делятся, когда выходят из области действия, как обычно, поэтому будьте осторожны, если ваша лямбда не является локальной: внутри ее тела она может ссылаться на объект, который уже был уничтожен.