Что происходит с лямбдой, которая, кажется, удаляет себя во время ее работы? [Дубликат]

Я использую maven для моего проекта, и когда я делаю mvn clean install и пытаюсь запустить программу, он выдает исключение. Итак, я очищаю проект и запускаю его снова, и он работает для меня.

Я использую eclipse IDE.

Для:

Класс не найден Исключение при запуске теста Junit

Попробуйте запустить mvn clean test, как только он скомпилирует все тестовые классы (работал для меня).

15
задан Claudiu 18 July 2015 в 17:38
поделиться

4 ответа

Как уже было описано в других ответах, лямбды представляют собой, по существу, синтаксический сахар для легкого создания типов, которые обеспечивают пользовательскую реализацию operator(). Вот почему вы можете даже писать лямбда-вызовы, используя явную ссылку на operator(), например: int main() { return [](){ return 0; }.operator()(); }. Те же правила для всех нестатических функций-членов также применяются к лямбда-телам.

И эти правила позволяют уничтожать объект во время выполнения функции-члена, если функция-член не использует this после. Ваш пример необычный, более распространенным примером является нестатическая функция-член, выполняющая delete this;. Это сделало его в FAQ на C ++ , объяснив, что это разрешено.

Стандарт позволяет это, не обращаясь к нему, насколько мне известно. Он описывает семантику функций-членов таким образом, который не полагается на объект, который не уничтожается, поэтому реализации должны быть уверены, что позволить функциям-членам продолжать выполнение, даже если объекты будут уничтожены.

Итак, чтобы ответить ваши вопросы:

Или это то, что этот указатель лямбда теперь недействителен (указывает на освобожденную память), поэтому никакие захваты лямбда не могут быть доступны, но если он запускает код, t использовать что-либо, что он захватывает, это не неопределенное поведение?

Да, в значительной степени.

Кроме того, в том случае, когда лямбда является подвижной, любой другой?

Нет, это не так.

Единственный раз, когда возможно перемещение лямбда, возможно, после перемещения лямбда. В вашем примере operator() продолжает выполняться на исходном перемещенном и затем уничтоженном функторе.

6
ответ дан hvd 21 August 2018 в 02:01
поделиться

В конечном счете, в этом вопросе есть много деталей, которые не актуальны. Мы можем свести его к вопросу о достоверности:

struct A {
    something_unmovable m;

    void operator()() {
        delete this;
        // do something with m
    }
};

И спросить об этом. В конце концов, влияние resize() заключается в вызове деструктора объекта mid-function-call.

Стандарт сообщает нам в [class.cdtor], что:

< blockquote>

Для объекта с нетривиальным деструктором, ссылаясь на любой нестатический член или базовый класс объекта после завершения выполнения деструктора, приводит к неопределенному поведению.

So если деструктор something_unmovable является нетривиальным (что сделало бы деструктор A - или ваш лямбда - нетривиальным), любая ссылка на m после вызова деструктора - это неопределенное поведение. Если something_unmovable имеет тривиальный деструктор, то ваш код вполне приемлем. Если вы не выполняете что-либо после delete this (resize() в своем вопросе), то это совершенно правильное поведение.

До сих пор доступен доступ из вектор?

Да, функтор в vec[0] по-прежнему будет иметь m. Это может быть оригинальная лямбда - или это может быть копия оригинальной лямбды. Но будет m так или иначе.

3
ответ дан Barry 21 August 2018 в 02:01
поделиться

Вы можете обрабатывать лямбда-захваты, как обычные экземпляры структуры.

В вашем случае:

struct lambda_UUID_HERE_stuff
{
    std::vector<std::function<void()>> &vec;
    something_unmovable m;

    void operator()()
    {
        this->vec.resize(100);
    }
};

... и я считаю, что применяются все те же правила (что касается VS2013 )

Итак, это, по-видимому, еще один случай неопределенного поведения. То есть, если &vec указывает на вектор, содержащий экземпляр захвата, а операции внутри operator() вызывают изменение этого вектора.

4
ответ дан defube 21 August 2018 в 02:01
поделиться
  • 1
    Это довольно пусто, если вы не докажете, что это UB для структуры. – Lightness Races in Orbit 18 July 2015 в 18:16
  • 2
    @LightnessRacesinOrbit: Я должен был сказать «Если &vec указывает на вектор, содержащий структуру, то это UB. Обновление ... – defube 18 July 2015 в 18:29
  • 3
    Это похоже на часто задаваемые вопросы по C ++. Является ли законным (и моральным) для функции-члена сказать это? , где объясняется, что нестатическая функция-член может продолжать работать без UB, даже если объект будет уничтожен до тех пор, пока функция-член не получит доступ к объекту после его удаления. – hvd 18 July 2015 в 18:33
  • 4
    @hvd: Не уверен, что я покупаю это. Было бы лучше с цитатами. – Lightness Races in Orbit 18 July 2015 в 18:48
  • 5
    @LightnessRacesinOrbit Да, это было бы, но я не думаю, что это явно разрешено, просто косвенно. Это отсутствие каких-либо запретов, которые это допускают. Добавлено ответ, противоречащий этому. – hvd 18 July 2015 в 19:19

Объекты функций обычно можно копировать, поэтому ваша лямбда будет продолжать работать без какого-либо эффекта. Если он фиксирует по ссылке AFAIR, внутренняя реализация будет использовать std :: reference_wrapper, чтобы лямбда оставалась скопированной.

-1
ответ дан Richard Hodges 21 August 2018 в 02:01
поделиться
  • 1
    Я не покупаю это. Что должен делать объект функции, подлежащий перепрограммированию? – Lightness Races in Orbit 18 July 2015 в 18:16
  • 2
    Если m не движется, он должен быть скопирован, иначе лямбда-захват не сможет его захватить. Поэтому лямбда является скопируемой и не подвижной. Поэтому перераспределение векторов будет происходить с точки зрения копирования, а не для перемещения. Поэтому лямбда безопасна, потому что m является копией. – Richard Hodges 18 July 2015 в 18:30
  • 3
    Ум нет, потому что во время операции копирования или перемещения, инициированной автоматическим изменением вектора, уничтожается лямбда, которая выполняется. Вот в чем вопрос. – Lightness Races in Orbit 18 July 2015 в 18:47
  • 4
    Достаточно справедливо, так что это UB – Richard Hodges 18 July 2015 в 19:00
  • 5
    Да, я делаю, и ОП просит нас предоставить от него доказательства, что это UB или нет. Вы не можете просто сказать «да, это». – Lightness Races in Orbit 18 July 2015 в 20:16
Другие вопросы по тегам:

Похожие вопросы: