Frage Löschen einer std :: -Funktion in der Mitte des Aufrufs


Ist es undefiniertes Verhalten, eine std :: -Funktion mitten im Aufruf zu zerstören / zu löschen?

class Event {
  public:
    Event(std::function<void()> f) : func(std::move(f)) {}
    ~Event() {}
    std::function<void()> func;
};

int main()
{
    std::vector<Event> events;
    auto func = [&]() {
      events.pop_back();  
      std::cout << "event" << std::endl;
      // do more work  
    };

    events.emplace_back(std::move(func));
    events[0].func();

    return 0;
}

6
2017-08-09 20:22


Ursprung


Antworten:


Dies ist nicht definiert durch [res.on.Objects] p2:

Wenn auf ein Objekt eines Standardbibliothekstyps zugegriffen wird, und auf den Anfang   der Lebensdauer des Objekts passiert nicht vor dem Zugriff oder der   Zugriff erfolgt nicht vor dem Ende der Lebensdauer des Objekts, der   Das Verhalten ist nicht definiert, sofern nicht anders angegeben.

Der "Zugriff" besteht in diesem Fall aus dem Aufruf des Funktionsaufrufoperators des std::function. Das std::function Objektlebenszeit endete am pop_back() Anruf, in der Mitte des Zugangs. Daher erfolgt der Zugriff nicht vor dem Ende der Lebensdauer des Objekts, und das Verhalten ist nicht definiert.


6
2017-08-09 23:47



Ihr Code (das Bit, nach dem Sie fragen, d. H. Das Zerstören des Objekts innerhalb einer Member-Funktion) entspricht in etwa

struct A
{
  void f() { delete this; }
}

int main()
{
  A* a = new A;
  a.f();
}

Das funktioniert tatsächlich. Refcounted Ressourcen könnten etwas Ähnliches tun, wenn der Refcount in ihrem Bereich Null erreicht unref Funktion.

Beachten Sie, dass Sie möglicherweise die Ereignisliste und die Ereignisse selbst so miteinander verknüpfen möchten. Ein Ereignis sollte nicht über seine Umgebung (die Ereigniswarteschlange) wissen.


3
2017-08-09 20:28