Лямбда-захват объекта QFile

#c #qt #visual-studio-2012 #lambda

#c #qt #visual-studio-2012 #лямбда

Вопрос:

Я хочу сохранить файл внутри лямбда-функции. Я могу работать с ним вне лямбда-выражения, но как только я передаю его в качестве ссылки и хочу проверить его существование после его загрузки, мое приложение выходит из строя в этой строке : if (workFile.exists() amp;amp; !workFile.remove()) { .

 QFile workFile("path/to/file.bat");

[..]

if (!workFile.exists()) {
    [..] download file amp; such
    QObject::connect(amp;mng, amp;FileManager::onDownload, this, [=, amp;workFile] (const QStringamp; name) {
        if (workFile.exists() amp;amp; !workFile.remove()) {
            qDebug() << "File was not downloaded correctly.";
        }
    });
}
 

Обратная трассировка:

введите описание изображения здесь

Почему это не работает? Как я должен правильно захватить QFile?

Комментарии:

1. @Mike Хороший улов, опубликуйте его в качестве ответа!

Ответ №1:

При захвате объекта по ссылке, если лямбда-выражение вызывается после окончания срока службы объекта, вы получаете висячую ссылку. Вы всегда должны убедиться, что объекты, передаваемые по ссылке, остаются действительными при вызове лямбда-выражения.

В вашем примере QFile объект выходит за пределы области видимости до фактического вызова лямбда-выражения, это происходит потому, что ваш FileManager emits onDownload после завершения вашей функции, лямбда-выражение получает ссылку на недопустимый объект, и вы получаете сбой.

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

Если вам действительно нужно захватить старый QFile экземпляр, вы должны убедиться, что его время жизни действительно при вызове лямбда-выражения (вы можете сделать это, выделив его в куче, используя new и delete редактируя его самостоятельно, когда закончите).