Rozważmy następującą minimalną przykład:std :: list i std :: for_each: gdzie jest mój koniec?
#include <functional>
#include <algorithm>
#include <list>
int main() {
std::list<std::function<void()>> list;
list.push_back([&list](){ list.push_back([](){ throw; }); });
std::for_each(list.cbegin(), list.cend(), [](auto &&f) { f(); });
}
to kompiluje i zgłasza wyjątek, w okresie czasu.
Domyślam się, że tylko pierwsza lambda jest wykonywany przez std::for_each
, ale widocznie się myliłem: jeśli dołączy kolejny lambda na końcu listy, iteracja dotrze również, że lambda.
Załóżmy przywrócić przykład (push_front
zamiast push_back
i crbegin
/crend
zamiast cbegin
/cend
):
#include <functional>
#include <algorithm>
#include <list>
int main() {
std::list<std::function<void()>> list;
list.push_front([&list](){ list.push_front([](){ throw; }); });
std::for_each(list.crbegin(), list.crend(), [](auto &&f) { f(); });
}
Ponieważ w poprzednim przykładzie, spodziewałem się tego, aby skompilować i awarii, jak również.
Zamiast tego kompiluje się i nie ulega awarii. Tym razem funkcja przesunięta na początek listy nie zostanie wykonana.
pytanie jest dość prosta: jest to prawidłowe?
Dlaczego dwa przykłady są sprzeczne z intuicją?
W pierwszym przypadku Spodziewałem się czegoś innego i nie miałem racji, że nie jest to problem.
W każdym razie oczekiwałbym spójności między dwiema pętlami. To znaczy, druga funkcja jest wykonywana w jednym przypadku i nie jest wykonywana w drugim przypadku, ale ja iteracji z rozpocząć do koniec w obu przypadkach.
Co jest nie tak w moim rozumowaniu?
Compiler używane? –
@GillBates Zarówno GCC 6.1 i clang 3.9 działają zgodnie z opisem w pytaniu. Czy to istotne? Nie sądziłem, że może to być problem kompilatora. – skypjack
Czy nie powinien on faktycznie dodać lambda (pierwszy przykład)? Iteratory nie są unieważniane jak w przypadku 'std :: vector'. – vsoftco