简体   繁体   English

全局与局部函数对象

[英]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. 同样,当按值而不是按引用捕获formatStr时,全局版本也适用。

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. 在所有情况下,当您调用parseDateTimeWithFormat时,都将给出字符串文字。 Since that isn't a std::string a temporary one is created for you. 由于这不是std::string会为您创建一个临时的。 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. 然后返回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 . 不幸的是,一旦表达式结束,在您调用parseDateTimeWithFormat地方结束后,该临时文件便被销毁,并且剩下对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. 就像您发现的那样,解决方法是按值捕获,因此lambda具有其自己的副本,并且您不会尝试引用不再存在的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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