我们不能管理std :: map <string,ofstream>吗?

时间:2017-03-21 07:28:08

标签: c++11 ofstream

我尝试创建输出时序结果并从预定义的字符串调用任何流:

#include <cstring>                                                                                                                  
#include <map>
#include <fstream>

using namespace std;

int main(void) {
    map<string,ofstream> Map;
    ofstream ofs("test_output");
    string st="test";
    Map[st] = ofs;
    return 0;
}

我收到以下错误;我该如何解决?

a.cpp: In function ‘int main()’:
a.cpp:11:8: error: use of deleted function ‘std::basic_ofstream<_CharT, _Traits>& std::basic_ofstream<_CharT, _Traits>::operator=(const std::basic_ofstream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’
  Map[s]=ofs;
        ^
In file included from a.cpp:3:0:
/usr/include/c++/5/fstream:744:7: note: declared here
   operator=(const basic_ofstream&) = delete;

       ^
In file included from a.cpp:3:0:
/usr/include/c++/5/fstream:744:7: note: declared here
   operator=(const basic_ofstream&) = delete; 

2 个答案:

答案 0 :(得分:4)

这是因为您无法复制ostream只能移动它。您收到此错误,因为删除了复制赋值运算符。相反,地图必须拥有流的所有权:

Map[st] = std::move(ofs);

现在这也意味着在迭代地图时必须小心。您必须避免复制,并避免从地图中窃取所有权。

另请注意,不建议using namespace std;

答案 1 :(得分:4)

由于std::ostream不可复制(复制构造函数和赋值运算符被标记为已删除),您必须直接在地图中构造ofstream(例如使用std::map::emplace())或使用移动赋值。 / p>

就地构建

基本上有两种方法,一种是地图中的默认构造流(前C ++ 11),或者是调用std::map::emplace()来提供ofstream构造函数参数。

使用default-construction(甚至可以在C ++ 11之前使用):

map<string,ofstream> m;

// default-construct stream in map    
ofstream& strm = m["test"];
strm.open("test_output");
strm << "foo";

使用安置:

// 1st parameter is map key, 2nd parameter is ofstream constructor parameter    
auto res = m.emplace("test", "test_output");
auto& strm = res.first->second;
strm << "bar";

移动作业

我们可以首先在地图之外构建流,然后通过调用rvalue将其转换为std::move(),并使用move assignment operator将其移动到地图中:

map<string,ofstream> m;    
ofstream strm("test_output");
m["test"] = std::move( strm );
// strm is not "valid" anymore, it has been moved into the map

如果我们直接将流创建为rvalue,我们甚至可以删除std::move()

m["test"] = ofstream("test_output");

移动分配的效率低于其他方法,因为首先在地图中默认构造一个流,然后由移动分配的流替换。

Live demo of all three methods.

注意:为简洁起见,示例代码省略了任何错误处理。应在打开后和每次流操作后检查流的状态。