I have a function that returns another function, which captures the parameter of the wrapper function. the local version works, but the global version doesn't, and I don't understand why:
#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;
}
output:
(empty string)
-1
%Y-%m-%dT%H:%M:%SZ
1538989748
also, when capturing formatStr
by value instead of by reference, the global version works, too.
Your local version might "work" but it also suffers from the same thing as the global version, which is undefined behavior. In all cases when you call parseDateTimeWithFormat
you give a string literal. Since that isn't a std::string
a temporary one is created for you. That string is what you capture in
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;
};
and return out of the lambda. Unfornetly, as soon as the expresion ends where you called parseDateTimeWithFormat
that temporary is destroyed and you are left with a dangling reference to formatStr
. The fix, like you found, is to capture by value so the lambda has it's own copy and you don't try to refer to something that doesn't exist anymore.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.