C++ 映射条目作为参考
C++ map entry as reference
基本上我有一张包含一些条目的地图。我使用自定义构造函数创建条目并删除默认构造函数。在一个条目中,我想更新一个值。我想通过引用条目然后调用 update/set 方法来实现。
我有以下代码:
#include <map>
#include <string>
class CacheEntry
{
public:
CacheEntry() = delete;
CacheEntry(const int value1)
: value1(value1)
{
}
void SetValue2(const int value2)
{
this->value2 = value2;
}
private:
const int value1;
int value2;
};
class Cache
{
public:
void SetValue2(const std::string& name, const int value2)
{
if (entries.count(name) == 0)
{
return;
}
CacheEntry& entry = entries[name];
entry.SetValue2(value2);
}
private:
std::map<std::string,CacheEntry> entries;
};
编译时出现如下错误:
In file included from /usr/include/c++/9/bits/stl_map.h:63,
from /usr/include/c++/9/map:61,
from test.cpp:1:
/usr/include/c++/9/tuple: In instantiation of ‘std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const std::__cxx11::basic_string<char>; _T2 = CacheEntry]’:
/usr/include/c++/9/tuple:1663:63: required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; _Args2 = {}; _T1 = const std::__cxx11::basic_string<char>; _T2 = CacheEntry]’
/usr/include/c++/9/ext/new_allocator.h:147:4: required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >]’
/usr/include/c++/9/bits/alloc_traits.h:484:4: required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> > >]’
/usr/include/c++/9/bits/stl_tree.h:614: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<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >*]’
/usr/include/c++/9/bits/stl_tree.h:631:4: 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<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >*]’
/usr/include/c++/9/bits/stl_tree.h:2455:13: 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<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >]’
/usr/include/c++/9/bits/stl_map.h:499:8: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = CacheEntry; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = CacheEntry; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char>]’
test.cpp:33:36: required from here
/usr/include/c++/9/tuple:1674:70: error: use of deleted function ‘CacheEntry::CacheEntry()’
1674 | second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
| ^
test.cpp:7:3: note: declared here
7 | CacheEntry() = delete;
| ^~~~~~~~~~
为什么编译器会在 CacheEntry& entry = entries[name];
处创建一个新对象?我希望引用地图中已经存在的对象。
我知道我可以删除 CacheEntry() = delete;
,但这不是我想要的。
Why does the compiler create a new object at CacheEntry& entry = entries[name];
?
map::operator[]
creates a new default-constructed entry if the specified key doesn't exist. Even though you are using map::count()
以确保不会实际创建新条目,operator[]
后面的实现代码仍然需要正确编译。这意味着如果你想使用 operator[]
,map
的条目必须有一个有效的默认构造函数。
否则,根本不要使用operator[]
,而是使用map::find()
,例如:
void SetValue2(const std::string& name, const int value2)
{
auto iter = entries.find(name);
if (iter != entries.end())
iter->second.SetValue2(value2);
}
I expect a reference to the already existing object in the map.
正确 - 在运行时。但是在编译时,编译器无法知道一个对象是否已经存在。
基本上我有一张包含一些条目的地图。我使用自定义构造函数创建条目并删除默认构造函数。在一个条目中,我想更新一个值。我想通过引用条目然后调用 update/set 方法来实现。
我有以下代码:
#include <map>
#include <string>
class CacheEntry
{
public:
CacheEntry() = delete;
CacheEntry(const int value1)
: value1(value1)
{
}
void SetValue2(const int value2)
{
this->value2 = value2;
}
private:
const int value1;
int value2;
};
class Cache
{
public:
void SetValue2(const std::string& name, const int value2)
{
if (entries.count(name) == 0)
{
return;
}
CacheEntry& entry = entries[name];
entry.SetValue2(value2);
}
private:
std::map<std::string,CacheEntry> entries;
};
编译时出现如下错误:
In file included from /usr/include/c++/9/bits/stl_map.h:63,
from /usr/include/c++/9/map:61,
from test.cpp:1:
/usr/include/c++/9/tuple: In instantiation of ‘std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const std::__cxx11::basic_string<char>; _T2 = CacheEntry]’:
/usr/include/c++/9/tuple:1663:63: required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; _Args2 = {}; _T1 = const std::__cxx11::basic_string<char>; _T2 = CacheEntry]’
/usr/include/c++/9/ext/new_allocator.h:147:4: required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >]’
/usr/include/c++/9/bits/alloc_traits.h:484:4: required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> > >]’
/usr/include/c++/9/bits/stl_tree.h:614: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<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >*]’
/usr/include/c++/9/bits/stl_tree.h:631:4: 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<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >*]’
/usr/include/c++/9/bits/stl_tree.h:2455:13: 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<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >]’
/usr/include/c++/9/bits/stl_map.h:499:8: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = CacheEntry; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = CacheEntry; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char>]’
test.cpp:33:36: required from here
/usr/include/c++/9/tuple:1674:70: error: use of deleted function ‘CacheEntry::CacheEntry()’
1674 | second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
| ^
test.cpp:7:3: note: declared here
7 | CacheEntry() = delete;
| ^~~~~~~~~~
为什么编译器会在 CacheEntry& entry = entries[name];
处创建一个新对象?我希望引用地图中已经存在的对象。
我知道我可以删除 CacheEntry() = delete;
,但这不是我想要的。
Why does the compiler create a new object at
CacheEntry& entry = entries[name];
?
map::operator[]
creates a new default-constructed entry if the specified key doesn't exist. Even though you are using map::count()
以确保不会实际创建新条目,operator[]
后面的实现代码仍然需要正确编译。这意味着如果你想使用 operator[]
,map
的条目必须有一个有效的默认构造函数。
否则,根本不要使用operator[]
,而是使用map::find()
,例如:
void SetValue2(const std::string& name, const int value2)
{
auto iter = entries.find(name);
if (iter != entries.end())
iter->second.SetValue2(value2);
}
I expect a reference to the already existing object in the map.
正确 - 在运行时。但是在编译时,编译器无法知道一个对象是否已经存在。