c++ - Warum ist es beim Verschieben eines unique_ptr in ein Lambda nicht möglich, reset aufzurufen?




c++11 unique-ptr (3)

Wenn std::unique_ptr in das Lambda std::unique_ptr , ist es nicht möglich, reset() aufzurufen, da es dann anscheinend const ist:

error C2662: void std::unique_ptr<int,std::default_delete<_Ty>>::reset(int *) noexcept': cannot convert 'this' pointer from 'const std::unique_ptr<int,std::default_delete<_Ty>>' to 'std::unique_ptr<int,std::default_delete<_Ty>> &
#include <memory>
int main()
{
    auto u = std::unique_ptr<int>();
    auto l = [v = std::move(u)]{
        v.reset(); // this doesn't compile
    };
}
  1. Warum passiert das?
  2. Ist es möglich, std::unique_ptr auf eine andere Weise zu erfassen, die den Aufruf von reset() im Lambda (mit C ++ 17 oder höher) ermöglicht?

  1. Warum passiert das?

Weil Lambdas standardmäßig nicht veränderbar sind. Daher sind alle erfassten Objekte const. reset ist eine Nicht-Konstanten-Member-Funktion, die den eindeutigen Zeiger ändert.

  1. Ist es möglich, std :: unique_ptr auf eine andere Weise zu erfassen, mit der reset () im Lambda aufgerufen werden kann (mit C ++ 17 oder höher)?

Ja. Deklarieren Sie das Lambda als veränderlich:

[captures](arguments) mutable { body }
                      ^^^^^^^

Dies ist seit C ++ 11 möglich, wo Lambdas eingeführt wurden. Alle erfassten Nicht-Konstanten-Objekte eines veränderlichen Lambda sind Nicht-Konstanten-Kopien.


  1. Warum passiert das?

Weil der Funktionsaufruf Operator eines lambda ,

Sofern das Schlüsselwort mutable nicht im Lambda-Ausdruck verwendet wurde, ist der Funktionsaufruf-Operator const-qualifiziert und die Objekte, die durch Kopieren erfasst wurden, können innerhalb dieses operator() nicht geändert operator() .

und

  1. Ist es möglich, std::unique_ptr auf eine andere Weise zu erfassen, mit der reset() im Lambda aufgerufen werden kann reset()

Sie müssen es als mutable markieren.

änderbar: Ermöglicht Body, die per Kopie erfassten Parameter zu ändern und ihre Nicht-Konstanten-Member-Funktionen aufzurufen

z.B

auto l = [v = std::move(u)]() mutable {
    v.reset();
};

Um ein "Mitglied" des Lambda zu mutieren, benötigen Sie das Schlüsselwort mutable :

auto l = [v = std::move(u)] () mutable {
    v.reset();
};




capture-list