C ++ 11 лямбда-реализация и модель памяти

Я хотел бы получить некоторую информацию о том, как правильно думать о замыканиях C ++ 11 иstd::function с точки зрения того, как они реализованы и как обрабатывается память.

Хотя я не верю в преждевременную оптимизацию, у меня есть привычка тщательно обдумывать влияние моего выбора на производительность при написании нового кода. Я также занимаюсь программированием в реальном времени, например, на микроконтроллерах и для аудиосистем, где следует избегать недетерминированных пауз выделения / освобождения памяти.

Поэтому я хотел бы лучше понять, когда использовать или не использовать C ++ лямбда-выражения.

Насколько я понимаю, лямбда без захваченного замыкания в точности похожа на обратный вызов Си. Однако, когда среда захватывается либо по значению, либо по ссылке, в стеке создается анонимный объект. Когда значение-закрытие должно быть возвращено из функции, его оборачивают вstd::function, Что происходит с закрытием памяти в этом случае? Копируется из стека в кучу? Это освобождено всякий раз, когдаstd::function освобождается, т. е. подсчитывается ли ссылка какstd::shared_ptr?

Я представляю, что в системе реального времени я мог бы установить цепочку лямбда-функций, передавая B в качестве аргумента продолжения A, так что конвейер обработкиA->B создано. В этом случае замыкания A и B будут распределены один раз. Хотя я не уверен, будут ли они размещены в стеке или в куче. Однако в целом это кажется безопасным для использования в системе реального времени. С другой стороны, если B создает некоторую лямбда-функцию C, которую она возвращает, тогда память для C будет выделяться и освобождаться повторно, что было бы неприемлемо для использования в реальном времени.

В псевдокоде - цикл DSP, который, я думаю, будет безопасным в реальном времени. Я хочу выполнить обработку блока A, а затем B, где A вызывает свой аргумент. Обе эти функции возвращаютstd::function объекты, такf будетstd::function объект, где его окружение хранится в куче:

auto f = A(B);  // A returns a function which calls B
                // Memory for the function returned by A is on the heap?
                // Note that A and B may maintain a state
                // via mutable value-closure!
for (t=0; t<1000; t++) {
    y = f(t)
}

И тот, который я думаю, может быть плохо использовать в коде в реальном времени:

for (t=0; t<1000; t++) {
    y = A(B)(t);
}

И тот, где я думаю, что стековая память, вероятно, используется для закрытия:

freq = 220;
A = 2;
for (t=0; t<1000; t++) {
    y = [=](int t){ return sin(t*freq)*A; }
}

В последнем случае замыкание строится на каждой итерации цикла, но, в отличие от предыдущего примера, оно дешевое, потому что оно похоже на вызов функции, поэтому выделение кучи не производится. Кроме того, мне интересно, может ли компилятор "поднять" закрытие и внесение оптимизаций.

Это правильно? Спасибо.

Ответы на вопрос(2)

Ваш ответ на вопрос