调用STL map中自定义类成员函数时编译错误的解决方法
std::map访问自定义对象时的编译错误解决
我拥有一个键为整数、值为自定义myclass对象的std::map,希望通过该map调用myclass的成员函数,代码如下:
#include <map> #include <iostream> class myclass { private: int x; public: myclass(int y) { this->x = y; } int add_to_x(int y) const { return (this->x + y); } }; int main() { std::map<int, myclass> mymap; mymap.emplace(1, 10); mymap.emplace(2, 20); std::cout << mymap[1].add_to_x(100) << std::endl; std::cout << mymap[2].add_to_x(100) << std::endl; return 0; }
使用g++ 11.4.0版本编译这段代码时,出现以下编译错误:
In file included from /usr/include/c++/11/bits/stl_map.h:63, from /usr/include/c++/11/map:61, from test.cpp:1: /usr/include/c++/11/tuple: In instantiation of ‘constexpr std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {int&&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const int; _T2 = myclass]’: /usr/include/c++/11/tuple:1809:63: required from ‘constexpr std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {int&&}; _Args2 = {}; _T1 = const int; _T2 = myclass]’: /usr/include/c++/11/bits/stl_construct.h:97:14: required from ‘constexpr decltype (::new(void*(0)) _Tp) std::construct_at(_Tp*, _Args&& ...) [with _Tp = std::pair<const int, myclass>; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; decltype (::new(void*(0)) _Tp) = std::pair<const int, myclass>*]’: /usr/include/c++/11/bits/alloc_traits.h:518:4: required from ‘static constexpr void std::allocator_traits<std::allocator<_Up> >::construct(std::allocator_traits<std::allocator<_Up> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const int, myclass>; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const int, myclass> >; std::allocator_traits<std::allocator<_Up> >::allocator_type = std::allocator<std::_Rb_tree_node<std::pair<const int, myclass> > >]’: /usr/include/c++/11/bits/stl_tree.h:595:32: required from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_construct_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, myclass>; _KeyOfValue = std::_Select1st<std::pair<const int, myclass> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, myclass> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, myclass> >*]’: /usr/include/c++/11/bits/stl_tree.h:612:21: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, myclass>; _KeyOfValue = std::_Select1st<std::pair<const int, myclass> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, myclass> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, myclass> >*]’: /usr/include/c++/11/bits/stl_tree.h:2431:33: required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, myclass>; _KeyOfValue = std::_Select1st<std::pair<const int, myclass> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, myclass> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree<int, std::pair<const int, myclass>, std::_Select1st<std::pair<const int, myclass> >, std::less<int>, std::allocator<std::pair<const int, myclass> > >::iterator; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree<int, std::pair<const int, myclass>, std::_Select1st<std::pair<const int, myclass> >, std::less<int>, std::allocator<std::pair<const int, myclass> > >::const_iterator]’: /usr/include/c++/11/bits/stl_map.h:520:37: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = int; _Tp = myclass; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, myclass> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = myclass; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]’: test.cpp:27:29: required from here /usr/include/c++/11/tuple:1820:9: error: no matching function for call to ‘myclass::myclass()’ 1820 | second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test.cpp:9:17: note: candidate: ‘myclass::myclass(int)’ 9 | myclass(int y) | ^~~~~~~ test.cpp:9:17: note: candidate expects 1 argument, 0 provided test.cpp:4:7: note: candidate: ‘constexpr myclass::myclass(const myclass&)’ 4 | class myclass | ^~~~~~~ test.cpp:4:7: note: candidate expects 1 argument, 0 provided test.cpp:4:7: note: candidate: ‘constexpr myclass::myclass(myclass&&)’ test.cpp:4:7: note: candidate expects 1 argument, 0 provided
我理解错误提示是说,当使用[]运算符访问mymap时,它尝试创建myclass的新对象,但我只想获取已插入到map中的myclass对象的引用,该如何实现?
问题原因
std::map的operator[]有一个特殊行为:如果访问的键不存在,它会自动默认构造一个对应类型的对象并插入到map中。这要求map的值类型必须提供无参的默认构造函数,而你的myclass只定义了带int参数的构造函数,没有默认构造函数,因此编译失败。
解决方案
1. 使用map::find()方法(推荐,安全无副作用)
find()方法只会查找键是否存在,不会自动插入新元素。找到则返回指向该元素的迭代器,否则返回map::end()。使用时需要先判断迭代器是否有效:
auto it = mymap.find(1); if (it != mymap.end()) { std::cout << it->second.add_to_x(100) << std::endl; }
2. 使用map::at()方法(C++11及以上)
at()方法会直接返回对应值的引用,如果键不存在会抛出std::out_of_range异常,不需要值类型有默认构造函数。适合确定键一定存在的场景:
std::cout << mymap.at(1).add_to_x(100) << std::endl; std::cout << mymap.at(2).add_to_x(100) << std::endl;
3. 给myclass添加默认构造函数(不推荐,除非业务需要)
如果确实需要默认构造的myclass对象,可以添加无参构造函数:
class myclass { private: int x; public: myclass() : x(0) {} // 指定合理的默认值 myclass(int y) : x(y) {} int add_to_x(int y) const { return x + y; } };
内容的提问来源于stack exchange,提问作者Setu
相关产品推荐
相关产品推荐

