将文件流插入到标准::映射
Insert File stream to std::map
我正在尝试使用文件流实现std::map(实际上是std::p air)。因为标准 c++ 文件流(ifstreams ofstream 和 fstream)不可复制,所以选择落在了 stdio 的 FILE 上。这是最简单的类包装器:
#include <stdio.h>
class FileWriter
{
public:
FileWriter(const char* fileName)
{
_fs = fopen(fileName, "w");
}
~FileWriter()
{
fclose(_fs);
}
private:
FILE* _fs;
};
让我们尝试将此类用作 std::map 中的模板参数:
int main()
{
std::map<int, FileWriter> a{ { 1, FileWriter("fl.fl") } };
}
它编译得很好,但我收到一个运行时错误 - 内存转储。调试器显示析构函数 ~FileWriter() 执行了两次。为什么会发生这种情况以及如何避免此错误?
代码的问题在于复制构造函数只是复制了FILE*
,并且在将对象插入std::map<...>
时创建了一个临时对象。结果,传入的FILE*
得到了fclose()
d,并且在尝试访问FILE*
时得到了未定义的行为。
在 C++11 中,可以将流emplace()
到地图中:
std::map<int, std::ofstream> streams;
streams.emplace(42, std::ofstream("hello, world"));
您使用临时地图创建了地图,该临时地图将复制到地图中需要的位置。由于您没有提供复制构造函数,因此使用默认值,它将简单地复制_fs
。 调用临时的析构函数,关闭文件。然后,当地图被销毁时,将在放置在地图中的副本上再次调用析构函数。
您需要为自己的副本构造函数提供适当的语义。但是语义应该是什么?由于某种原因,IO流不可复制。你可以让你的类只移动,但这样你就处于与iostream完全相同的情况,因为它们也是只移动的。
另请参阅:http://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29
因为标准 c++ 文件流(ifstreams ofstream 和 fstream)是不可复制的"
是的,因为复制流毫无意义。
流不是容器;它们是数据流。
不要试图解决这个问题。
构造 FileWriter 类,然后复制到映射中(复制构造)。 这就是析构函数被调用两次的原因。
- 如何将整数向量插入到键中,标准::映射的值
- 标准::映射::合并的计算时间复杂度
- 标准::映射转换器模板
- 从另一个常量标准::映射初始化一个常量标准::映射的一部分
- 替换标准::映射值时崩溃
- 如果可能,标准::映射分配是否静态
- 如何在标准::映射中try_emplace POD 结构?
- 多类型标准映射
- 五月标准::映射键地址值数
- 模板标准::映射为类成员
- 模板标准::映射::迭代器实例化
- 推进标准映射的迭代器
- 标准::映射的自定义分配器失败
- 将文件流插入到标准::映射
- 增加迭代器标准映射
- 如何初始化标准::映射项的向量
- SWIG 不可变标准::映射引用
- 标准:映射与运算符=不匹配
- 标准::映射 标准::集合包含重复的键
- 从文本文件加载标准::映射