【问题标题】:how to do a map to ofstreams?如何映射到ofstreams?
【发布时间】:2022-01-24 05:27:24
【问题描述】:

有一个与此类似的问题,但没有得到回答。

我正在尝试创建std::ofstream 对象的映射,但我无法构建代码。

到目前为止我已经尝试过

//std::map<std::string, std::ofstream> my_files;  //this fails
std::map<std::string, std::ofstream& > my_files;

for(auto & member: members){
   filename=GetFileName();
   //create the file
   std::ofstream thefile(filename);

   my_files[member.first]=thefile;
}
//Here I use the ofstreams in the map to write etc

我尝试了第一行(注释),得到了this error。使用已删除的功能。所以我把它改成上面的那行,但我仍然得到同样的错误错误:use of deleted function ‘std::basic_ofstream

如何构建 ofstream 对象的映射?

注意:在类似的问题中,有人建议使用字符串映射,但使用 ofstream 映射的原因是我不会在每次想要对每个文件进行最小更改时打开和关闭文件.

【问题讨论】:

  • 无法复制流。您也许可以移动它们或使用 emplace 就地构建它们,但我自己从未尝试过。
  • 那么同时处理多个流的好方法是什么?
  • 我个人的感觉是,除非您正在积极地阅读或写入文件,否则最好不要让文件保持打开状态。我会读取您需要的任何数据,在内存中对其进行操作,然后一次将其全部写出。
  • @RetiredNinja 根据文件的大小,这可能不可行。
  • “那么同时处理多个流的好方法是什么?” 取决于您所说的“处理”。您要解决什么实际问题?为什么您发现同时打开多个文件很有用?您知道文件句柄通常是limited system resource,是吗?

标签: c++ dictionary file-writing


【解决方案1】:

首先,引用不能存储在容器中。但是您似乎想要存储 std::ofstream 本身,而不是对其的引用,因为您的 std::ofstream 对象将在循环体的末尾被销毁,从而在地图中留下一个悬空的引用,所以:

std::map<std::string, std::ofstream > my_files;

其次,std::ofstream 等流对象是不可复制的,因此不能简单地将它们复制到地图中。

但是,它们是可移动的,因此您可以将它们移动到地图中:

my_files[member.first] = std::move(thefile);

(需要#include&lt;utility&gt;)或者直接在赋值中构造它:

my_files[member.first] = std::ofstream(filename);

有关std::move的解释,如果你以前没有见过,请参阅this question

【讨论】:

    【解决方案2】:

    问题引用本身不是对象。引用引用到其他对象。因此,您不能将引用存储在容器中。

    您可以解决此问题,方法是替换 my_files[member.first]=thefile; 为:

    my_files.emplace(member.first, std::ofstream(filename));
    

    另外,替换 std::map&lt;std::string, std::ofstream&amp; &gt; my_files; 为:

    std::map<std::string, std::ofstream > my_files; //removed the &
    

    修改代码

    std::map<std::string, std::ofstream > my_files; //removed the &
    
    for(auto & member: members){
       filename=GetFileName();
    
       my_files.emplace(member.first, std::ofstream(filename)); //ADDED THIS
    }
    

    【讨论】:

    • 如果我做my_files[member.first]=std::ofstream(filename);会不会一样?
    • @KansaiRobot 是的,你可以写my_files[member.first]=std::ofstream(filename);。也只是为了进一步阅读,来自this 文章,Stream 对象不能简单地复制分配。请注意,std::ofstream 有一个已删除的复制构造函数,因此无法复制。但是你可以使用std::movemove他们。
    • @KansaiRobot 是的,您也可以使用my_files[member.first]=std::ofstream(filename);。但请注意my_files[member.first]=std::ofstream(filename); 将使用std::ofstream::operator=
    猜你喜欢
    • 1970-01-01
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-01
    • 2018-06-18
    • 2017-05-02
    • 1970-01-01
    相关资源
    最近更新 更多