我们不能管理 std::map<string,ofstream> 吗?
Can't we manage std::map<string,ofstream>?
我尝试创建用于输出计时结果并从预定义字符串调用任何 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;
这是因为您无法复制 ostream
,您只能移动它。您收到此错误是因为复制赋值运算符被删除。相反,地图必须拥有流的所有权:
Map[st] = std::move(ofs);
现在这也意味着您在遍历地图时必须小心。您必须避免复制并避免窃取地图的所有权。
附带说明,请注意不推荐 using namespace std;
。
由于 std::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";
使用安置:
// 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";
移动作业
我们可以先在map外构造stream,把它变成一个rvalue by calling std::move()
and use move assignment operator移动到map里面:
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.
注意: 为简洁起见,示例代码省略了任何错误处理。应在打开后和每次流操作后检查流的状态。
我尝试创建用于输出计时结果并从预定义字符串调用任何 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;
这是因为您无法复制 ostream
,您只能移动它。您收到此错误是因为复制赋值运算符被删除。相反,地图必须拥有流的所有权:
Map[st] = std::move(ofs);
现在这也意味着您在遍历地图时必须小心。您必须避免复制并避免窃取地图的所有权。
附带说明,请注意不推荐 using namespace std;
。
由于 std::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";
使用安置:
// 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";
移动作业
我们可以先在map外构造stream,把它变成一个rvalue by calling std::move()
and use move assignment operator移动到map里面:
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.
注意: 为简洁起见,示例代码省略了任何错误处理。应在打开后和每次流操作后检查流的状态。