Глобальный или локальный функциональный объект - PullRequest
0 голосов
/ 08 октября 2018

У меня есть функция, которая возвращает другую функцию, которая записывает параметр функции-оболочки.локальная версия работает, но глобальная версия не работает, и я не понимаю, почему:

#include <iostream>
#include <sstream>
#include <iomanip>


const auto& parseDateTimeWithFormat = [](const std::string& formatStr) {
    return [&formatStr](const std::string& dateTimeStr) {
        std::cout << formatStr << std::endl;
        tm t = {};
        std::istringstream ss(dateTimeStr);
        ss >> std::get_time(&t, formatStr.c_str());
        const int timestamp = (int)mktime(&t);
        return timestamp;
    };
};


const auto& parseDateTime1 = parseDateTimeWithFormat("%Y-%m-%dT%H:%M:%SZ");


int main(int argc, const char* argv[]) {
    int ts1 = parseDateTime1("2018-10-08T10:09:08Z");
    std::cout << ts1 << std::endl;

    const auto& parseDateTime2 = parseDateTimeWithFormat("%Y-%m-%dT%H:%M:%SZ");
    int ts2 = parseDateTime2("2018-10-08T10:09:08Z");
    std::cout << ts2 << std::endl;

    return 0;
}

вывод:

(empty string)
-1
%Y-%m-%dT%H:%M:%SZ
1538989748

также при захвате formatStr по значениювместо ссылки, глобальная версия тоже работает.

1 Ответ

0 голосов
/ 08 октября 2018

Ваша локальная версия может «работать», но она также страдает тем же, что и глобальная версия, что является неопределенным поведением.Во всех случаях, когда вы вызываете parseDateTimeWithFormat, вы даете строковый литерал.Так как это не std::string, временный создан для вас.Эта строка - то, что вы захватываете в

return [&formatStr](const std::string& dateTimeStr) {
    std::cout << formatStr << std::endl;
    tm t = {};
    std::istringstream ss(dateTimeStr);
    ss >> std::get_time(&t, formatStr.c_str());
    const int timestamp = (int)mktime(&t);
    return timestamp;
};

и возвращаете из лямбды.Unfornetly, как только закончится выражение, где вы назвали parseDateTimeWithFormat, этот временный объект уничтожен, и у вас останется свисающая ссылка на formatStr.Как вы обнаружили, исправление заключается в захвате по значению, чтобы у лямбды была собственная копия, и вы не пытались ссылаться на то, что больше не существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...