GCC4.4.7下将ifstream存入std::map编译失败求助
问题:GCC 4.4.7下无法将std::ifstream存入std::map
我希望将std::ifstream对象存入std::map以便后续读取文件内容,但使用不支持C++11的旧版GCC 4.4.7编译代码时无法通过。
示例代码
#include <iostream> #include <fstream> #include <map> int main() { std::map<std::string, std::ifstream> DicoRCALbin; DicoRCALbin["a"] = std::ifstream("M3-6I_10.rcal_0001.bin", std::ios_base::binary); }
编译报错信息(中文翻译)
$ g++ problem.cpp In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ios:39, from /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:40, from /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/iostream:40, from test.cpp:1: /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/ios_base.h: 在成员函数‘std::basic_ios<char, std::char_traits<char> >& std::basic_ios<char, std::char_traits<char> >::operator=(const std::basic_ios<char, std::char_traits<char> >&)’中: /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/ios_base.h:793: 错误: ‘std::ios_base& std::ios_base::operator=(const std::ios_base&)’是私有的 /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/iosfwd:47: 错误: 在该上下文中 /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/iosfwd: 在成员函数‘std::basic_istream<char, std::char_traits<char> >& std::basic_istream<char, std::char_traits<char> >::operator=(const std::basic_istream<char, std::char_traits<char> >&)’中: /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/iosfwd:53: 注意: 首次需要合成方法‘std::basic_ios<char, std::char_traits<char> >& std::basic_ios<char, std::char_traits<char> >::operator=(const std::basic_ios<char, std::char_traits<char> >&)’在此处 /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/iosfwd: 在成员函数‘std::basic_ifstream<char, std::char_traits<char> >& std::basic_ifstream<char, std::char_traits<char> >::operator=(const std::basic_ifstream<char, std::char_traits<char> >&)’中: /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/iosfwd:81: 注意: 首次需要合成方法‘std::basic_istream<char, std::char_traits<char> >& std::basic_istream<char, std::char_traits<char> >::operator=(const std::basic_istream<char, std::char_traits<char> >&)’在此处 /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/streambuf: 在成员函数‘std::basic_filebuf<char, std::char_traits<char> >& std::basic_filebuf<char, std::char_traits<char> >::operator=(const std::basic_filebuf<char, std::char_traits<char> >&)’中: /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/streambuf:778: 错误: ‘std::basic_streambuf<_CharT, _Traits>& std::basic_streambuf<_CharT, _Traits>::operator=(const std::basic_streambuf<_CharT, _Traits>&) [with _CharT = char, _Traits = std::char_traits<char>]’是私有的 /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/iosfwd:78: 错误: 在该上下文中 /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/iosfwd: 在成员函数‘std::basic_ifstream<char, std::char_traits<char> >& std::basic_ifstream<char, std::char_traits<char> >::operator=(const std::basic_ifstream<char, std::char_traits<char> >&)’中: /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/iosfwd:81: 注意: 首次需要合成方法‘std::basic_filebuf<char, std::char_traits<char> >& std::basic_filebuf<char, std::char_traits<char> >::operator=(const std::basic_filebuf<char, std::char_traits<char> >&)’在此处 test.cpp: 在函数‘int main()’中: test.cpp:8: 注意: 首次需要合成方法‘std::basic_ifstream<char, std::char_traits<char> >& std::basic_ifstream<char, std::char_traits<char> >::operator=(const std::basic_ifstream<char, std::char_traits<char> >&)’在此处 [...]
原因分析
C++11标准之前,std::ifstream是不可拷贝的类型:它的拷贝构造函数和赋值运算符都被声明为私有。而代码中使用map::operator[]时,会先默认构造一个空的std::ifstream对象插入到map中,再尝试将临时创建的std::ifstream对象赋值给它,这一过程触发了被禁用的拷贝赋值操作,导致编译报错。
解决方案
方案1:存储指针而非对象
指针是可拷贝的类型,将map的value类型改为std::ifstream*,通过动态分配对象来存储:
#include <iostream> #include <fstream> #include <map> int main() { std::map<std::string, std::ifstream*> DicoRCALbin; // 动态创建ifstream对象并插入map DicoRCALbin["a"] = new std::ifstream("M3-6I_10.rcal_0001.bin", std::ios_base::binary); // 使用后记得释放内存,避免泄漏 for (std::map<std::string, std::ifstream*>::iterator it = DicoRCALbin.begin(); it != DicoRCALbin.end(); ++it) { delete it->second; } }
方案2:使用insert直接构造对象(需注意兼容性)
如果GCC 4.4.7支持在insert中直接构造std::pair,可以直接在map中构造std::ifstream对象,跳过默认构造和赋值的步骤:
#include <iostream> #include <fstream> #include <map> #include <utility> int main() { std::map<std::string, std::ifstream> DicoRCALbin; // 直接构造pair并插入,避免赋值 DicoRCALbin.insert(std::pair<std::string, std::ifstream>( "a", std::ifstream("M3-6I_10.rcal_0001.bin", std::ios_base::binary) )); }
注意:由于C++11前没有移动语义,部分旧编译器可能仍然无法通过这种方式编译,此时方案1会更稳妥。
内容的提问来源于stack exchange,提问作者lucd
相关产品推荐
相关产品推荐

