c++ - 全局与局部函数对象
问题描述
我有一个返回另一个函数的函数,该函数捕获包装函数的参数。本地版本有效,但全球版本无效,我不明白为什么:
#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
此外,当按值而不是按引用捕获时,全局版本也可以工作。
解决方案
您的本地版本可能“工作”,但它也遭受与全局版本相同的问题,这是未定义的行为。在所有情况下,当您调用时,您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;
};
并从 lambda 中返回。不幸的是,一旦表达式结束,您调用parseDateTimeWithFormat
该临时对象的位置就会被销毁,并且您会留下对formatStr
. 就像您发现的那样,解决方法是按值捕获,以便 lambda 拥有自己的副本,并且您不要尝试引用不再存在的东西。
推荐阅读
- django - Django 查询集可以生成带有自连接的 SQL 语句吗?
- node.js - 如果不存在则创建文档,否则返回 Null 或空:MongoDB
- python - 无法在 iterrows 中检索数据框
- android-studio - Android Studio 识别设备,但无法运行代码
- javascript - iFrame postMessage 和 addEventListener 不起作用
- sql-server - 在 VARCHAR 中选择带有尾随空格 SQL Server 时的未记录功能
- github - 使用 Github Desktop 将代码推送到 github 时出现错误,无法推送一些参考
- r - 通过分隔符解析文本文件并使用 R 输出多个文件
- javascript - 雷达不适合 div,切断了一些内容。我该如何解决?
- sql-server - 在 asp.net 核心视图中显示 Db 视图的结果集