2013-12-01 3 views
2

В Objective-C мы знаем, что блоки имеют 3 реализации во время выполнения.C++ лямбда-реализация во время выполнения

  1. NSGlobalBlock - то есть singleton во время выполнения, и создается в случае, если мы не используем значения переменных стека.
  2. NSStackBlock - это не singleton, и он выделяется на стек (не на куче), и создается, когда мы используем некоторые переменные стека.
  3. NSMallocBlock - это выделено на куче, и это используется, когда мы хотим хранить блоки как ivar или свойство какого-либо класса, или где угодно в куче f.e. @property (nonatomic, copy) MyBlockType myBlock; или когда используется Block_copy() функция. Это действительно важно, потому что NSMallocBlock сохраняет объекты из контекста, и этот факт может создать некоторые собственные циклы, если мы не будем использовать блоки правильно.

Итак, мой вопрос: «Где я могу найти полное объяснение C Лямбдами ++ выполнения, и как они обрабатываются компилятором Или могли бы вы объяснить, что Есть ли какие-либо конкретные проблемы, связанные с управлением памятью с использованием C++ лямбды?? Где выделены лямбды, на кучу или на стек? "

+0

"и он создается в случае, если мы не изменяем значения переменных стека с помощью модификатора __block." Нет. 'NSGlobalBlock' для блоков, которые не являются * замыканиями *, т. Е. Не захватывают какие-либо локальные переменные из внешней области. «и создается, когда мы используем модификаторы _block для некоторых переменных стека». Нет. Опять же, для любых блоков, которые являются * замыканиями *, т. Е. Используют локальную переменную из внешней области. Он не имеет переменной '__block'. – newacct

+0

@newacct вы правы, NSGlobalBlock просто может использовать статические переменные, спасибо! – BergP

ответ

2

Lambdas реализация специфична для компилятора.

Стандарт не указывает, где он выделяется память-накрест, но , как правило, они примерно эквивалентны old-school functors и они и их захваченные значения копируются в стек, как любой нормальный объект.

E.g.

std::vector<int> v{10,11,12,13}; 
std::for_each(v.begin(), v.end(), [](int& i) {i++;}); 

будет просто функцией без гражданства.

Или

std::vector<int> v{10,11,12,13}; 
int C = 10; 
int D = 20; 
std::for_each(v.begin(), v.end(), [C,&D](int& i) {i += C + D;}); 

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

Единственный раз, когда вы действительно размещаете лямбда-объект в куче, когда он преобразуется в std::function, то как это делается, зависит от реализации компилятора std::function.

void g(const std::function& f); 
// ... 
auto f = [=](int& i){i += C;}; // still on the stack (compiler-specific type) 
g(f); // std::function constructed, possibly on the heap 
Смежные вопросы