c++ - 结构绑定 std::tuple 中断 std::stringstream
问题描述
考虑以下代码:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <tuple>
auto read_data(std::ifstream& training_file) {
if (!training_file) {
throw std::runtime_error{"Error: could not open one or more files"};
}
std::stringstream training{};
training << training_file.rdbuf();
std::cout << training.str() << '\n';
return std::tie(training);
}
int main() {
std::ifstream input{"input.txt"};
auto [train] = read_data(input);
std::cout << train.str() << '\n';
std::cout << "x" << '\n';
}
并忽略我返回单个元素的事实std::tie
(最初我是tie
两个std::stringstream
对象,但 MCVE 不需要)。
该input.txt
文件如下所示:
0,0,0,0, 0,0,0,0,
注意 - 第二行之后没有换行符。
该程序的意外输出是:
0,0,0,0, 0,0,0,0, É$~ Ź , x
显然,该É$~ Ź ,
部分不应该存在。
请注意,我正在输出完全相同的文件内容。我不知道意外的部分是从哪里来的。
玩代码时它变得更加陌生。如果我注释掉std::cout << train.str() << '\n';
inmain()
并复制std::cout << training.str() << '\n';
line inread_data()
函数,则输出如预期:
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, x
所以它不是由std::stringstream::str
两次调用引起的。一定是使用了返回值造成的。
更重要的是?从两次执行该std::cout << train.str() << '\n';
行会导致程序以.main()
code 3
GDB 报告:
gdb: unknown target exception 0x80000001 at 0x7ff909e845c0
Thread 1 received signal ?, Unknown signal.
0x00007ff909e845c0 in ?? ()
但这还没有结束。如果我将文件内容更改为包含:
0 0
或者
0 0 0 0
0 0 0 0
输出再次符合预期(使用原始代码 - 一cout
进read_data()
一进main()
.
为了确保我没有被一些潜入我的文件的不可打印字符所欺骗,我使用 PowerShell 输出其十六进制表示,这导致有关原始文件内容的以下序列:
30 20 30 20 30 20 30 0D 0A 30 20 30 20 30 20 30
如您所见,我的文件中除了0
s、空格和之外什么都没有。carriage-return + line-feed
知道为什么会发生这种情况吗?有关完整信息,我使用的是 MinGW 的 GCC 8.2.0。
解决方案
这是本地的:
std::stringstream training{};
这将返回对所述本地的引用,包装在一个元组中:
return std::tie(training);
因此auto [train] = ...;
将名称初始化为train
悬空引用。程序的行为是未定义的。
如果您需要返回两个流(或更多),那么只需在您选择的元组/数组/自定义聚合中预先声明它们:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <tuple>
#include <array>
auto read_data() {
std::array<std::stringstream,2> trainings{
std::stringstream{},
std::stringstream{}
};
return trainings;
}
int main() {
auto train = read_data();
std::cout << train[1].str() << '\n';
std::cout << "x" << '\n';
}
复制省略保证额外的对象要么被完全删除,要么被构建到位。
推荐阅读
- javascript - Socket.io GET/POST 404
- api - 是否可以使用命令行在 TestRail 中发送报告?
- security - 蛮力字典攻击示例
- javascript - Lerna:我怎样才能获得成功发布的包?
- css - 如何在屏幕上居中 php 文本?
- asp.net - ASP.Net Core - 如何让外键关系处理 web-api 的 POST 请求?
- javascript - 使用 ObjectId 元素数组查询集合
- visual-studio - Visual Studio 不再运行/调试代码
- r - R 从 SurvFit 中提取数据
- python - 带有视图集查询集过滤器的 Django REST 框架中的路由器