J'aimerais avoir quelques informations sur la façon de penser correctement sur le C++11 fermetures et std::function
en termes de la façon dont ils sont mis en œuvre et le fonctionnement de la mémoire est gérée.
Bien que je ne crois pas que dans l'est de l'optimisation, j'ai l'habitude de considérer soigneusement l'impact sur les performances de mon choix lors de l'écriture de ce nouveau code. Je fais aussi une bonne quantité de programmation en temps réel, par exemple sur les microcontrôleurs et pour les systèmes audio, les cas de non-déterministe de l'allocation/libération de mémoire pauses sont à éviter.
C'est pourquoi j'aimerais développer une meilleure compréhension de quand utiliser ou ne pas utiliser C++ lambdas.
Ma compréhension est qu'un lambda sans capturé fermeture est exactement comme un C de rappel. Toutefois, lorsque l'environnement est capturé par valeur ou par référence, un objet anonyme est créé sur la pile. Lorsqu'une valeur de fermeture doit être retourné à partir d'une fonction, d'une enveloppe en std::function
. Ce qui se passe à la fermeture de la mémoire dans ce cas? Est-il copié à partir de la pile, le tas? Est-il libéré à chaque fois que l' std::function
est libéré, c'est à dire, est-il référence compté comme un std::shared_ptr
?
J'imagine que, dans un système temps-réel je pourrais mettre en place une chaîne de lambda fonctions, passage de B comme une continuation de l'argument à Un, de sorte qu'un pipeline de traitement A->B
est créé. Dans ce cas, A et B des fermetures seraient attribués une fois. Bien que je ne suis pas sûr de savoir si celles-ci seraient alloués sur la pile ou le tas. Cependant, en général, ce qui semble sûr à utiliser dans un système en temps réel. D'autre part, si B constructions certains lambda fonction de C, dont il retourne, alors que la mémoire C seraient attribués et libéré à plusieurs reprises, ce qui ne serait pas acceptable pour l'utilisation en temps réel.
En pseudo-code, un DSP boucle, ce qui, je pense, d'être en temps réel de sécurité. Je veux effectuer un traitement de bloc A, puis B, où les appels de son argument. Ces deux fonctions renvoient std::function
objets, de sorte que f
sera std::function
objet, lorsque son environnement est stockée sur le tas:
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)
}
Et qui je pense peut être mauvais pour l'utilisation en temps réel de code:
for (t=0; t<1000; t++) {
y = A(B)(t);
}
Et un autre où je pense que la pile de la mémoire est probablement utilisé pour la fermeture:
freq = 220;
A = 2;
for (t=0; t<1000; t++) {
y = [=](int t){ return sin(t*freq)*A; }
}
Dans ce dernier cas, la fermeture est construit à chaque itération de la boucle, mais contrairement à l'exemple précédent, il est bon marché parce que c'est comme un appel de fonction, pas de tas allocations sont faites. Par ailleurs, je me demande si un compilateur pourrait "l'ascenseur" de la fermeture et de faire un alignement des optimisations.
Est-ce correct? Je vous remercie.