简体   繁体   中英

Global vs. local function object

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM