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

mal*_*lea 4 ofstream c++11

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

\n\n
#include <cstring>                                                                                                                  \n#include <map>\n#include <fstream>\n\nusing namespace std;\n\nint main(void) {\n    map<string,ofstream> Map;\n    ofstream ofs("test_output");\n    string st="test";\n    Map[st] = ofs;\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我收到以下错误;我该如何修复它?

\n\n
#include <cstring>                                                                                                                  \n#include <map>\n#include <fstream>\n\nusing namespace std;\n\nint main(void) {\n    map<string,ofstream> Map;\n    ofstream ofs("test_output");\n    string st="test";\n    Map[st] = ofs;\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

zet*_*t42 5

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

就地施工

基本上有两种方法,要么在映射中默认构造流(C++11 之前),要么调用std::map::emplace()以提供ofstream构造函数参数。

使用默认构造(甚至可以在 C++11 之前使用):

map<string,ofstream> m;

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

使用安置:

// 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";
Run Code Online (Sandbox Code Playgroud)

移动作业

我们可以先在映射之外构造流,通过调用将其转换为右值std::move(),然后使用移动赋值运算符将其移动到映射中:

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
Run Code Online (Sandbox Code Playgroud)

std::move()如果我们直接将流创建为右值,我们甚至可以摆脱它:

m["test"] = ofstream("test_output");
Run Code Online (Sandbox Code Playgroud)

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

所有三种方法的现场演示。

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