You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 19:17:00