使用boost::mutex的std::map出现奇怪行为

5

我有这段代码:

////
// Default Namespaces
///

using namespace std;

typedef map <string, boost::shared_mutex>   t_map_shared_mutex;

int main(int argc, char** argv) {

    t_map_shared_mutex  list_lock;

    boost::shared_mutex global_lock;

    string          i = "ABC";

    boost::unique_lock < boost::shared_mutex > l_lock ( global_lock );

    boost::unique_lock < boost::shared_mutex > lock ( list_lock[i] );
        //Do Something with that lock
    lock.unlock();

    l_lock.unlock();

}

这会产生以下错误。据我理解(我可能很错),g++告诉我互斥锁被作为常量值传递了...而我看不出原因。
In file included from /usr/include/c++/4.4/utility:63,
                 from /usr/include/boost/config/no_tr1/utility.hpp:21,
                 from /usr/include/boost/config/select_stdlib_config.hpp:33,
                 from /usr/include/boost/config.hpp:40,
                 from /usr/include/boost/date_time/compiler_config.hpp:12,
                 from /usr/include/boost/date_time/posix_time/posix_time.hpp:14,
                 from prova.cpp:5:
/usr/include/c++/4.4/bits/stl_pair.h: In constructor ‘std::pair<_T1, _T2>::pair(const _T1&, const _T2&) [with _T1 = const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _T2 = boost::shared_mutex]’:
/usr/include/c++/4.4/bits/stl_map.h:450:   instantiated from ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = boost::shared_mutex, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex> >]’
prova.cpp:66:   instantiated from here
/usr/include/c++/4.4/bits/stl_pair.h:84: error: no matching function for call to ‘boost::shared_mutex::shared_mutex(const boost::shared_mutex&)’
/usr/include/boost/thread/pthread/shared_mutex.hpp:47: note: candidates are: boost::shared_mutex::shared_mutex()
/usr/include/boost/thread/pthread/shared_mutex.hpp:21: note:                 boost::shared_mutex::shared_mutex(boost::shared_mutex&)
/usr/include/c++/4.4/bits/stl_pair.h: In constructor ‘std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U1 = const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _U2 = boost::shared_mutex, _T1 = const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _T2 = boost::shared_mutex]’:
/usr/include/c++/4.4/ext/new_allocator.h:105:   instantiated from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex>]’
/usr/include/c++/4.4/bits/stl_tree.h:371:   instantiated from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(const _Val&) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Val = std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex>, _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex> >, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex> >]’
/usr/include/c++/4.4/bits/stl_tree.h:881:   instantiated from ‘std::_Rb_tree_iterator<_Val> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_(const std::_Rb_tree_node_base*, const std::_Rb_tree_node_base*, const _Val&) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Val = std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex>, _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex> >, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex> >]’
/usr/include/c++/4.4/bits/stl_tree.h:1215:   instantiated from ‘std::_Rb_tree_iterator<_Val> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique_(std::_Rb_tree_const_iterator<_Val>, const _Val&) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Val = std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex>, _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex> >, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex> >]’
/usr/include/c++/4.4/bits/stl_map.h:540:   instantiated from ‘typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, const std::pair<const _Key, _Tp>&) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = boost::shared_mutex, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex> >]’
/usr/include/c++/4.4/bits/stl_map.h:450:   instantiated from ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = boost::shared_mutex, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_mutex> >]’
prova.cpp:66:   instantiated from here
/usr/include/c++/4.4/bits/stl_pair.h:101: error: no matching function for call to ‘boost::shared_mutex::shared_mutex(const boost::shared_mutex&)’
/usr/include/boost/thread/pthread/shared_mutex.hpp:47: note: candidates are: boost::shared_mutex::shared_mutex()
/usr/include/boost/thread/pthread/shared_mutex.hpp:21: note:                 boost::shared_mutex::shared_mutex(boost::shared_mutex&)

如何解决这个问题?
2个回答

11

STL容器需要一个值类型的复制构造函数;由于互斥锁不能被复制,因此您无法直接将它们放入map中。相反,您必须使用指向互斥锁的指针(可能通过std::unique_ptrboost::ptr_map)。


2
@St0rM - 我认为你需要提高对标准容器的技能。在某些情况下,如果你知道自己在做什么,直接将对象放入容器中是可以的。但一般来说,你应该考虑将对象的指针(如std::map)放入容器中,而不是对象本身。容器可以根据需要在内部复制对象,因此你无法控制构造函数和析构函数何时被调用。 - T.E.D.
3
@TED: 你并不指的是普遍情况,是吗?在容器中使用指针通常是不正确的。 - GManNickG
我想要补充一点,虽然应该避免使用裸指针,但 RAII 容器(例如 std::unique_ptr)是可以的,如果没有这个选项,你可以使用指针感知容器,例如 ptr_map - 这样做的目的是确保在容器被销毁时自动进行内存释放。 - bdonlan
1
只要你能接受在对象被复制时可能会发生很多事情,那么是的。我经常在实时领域工作,通常情况下这是不可以的。如果“复制”可能会在我身上关闭并重新获取资源(例如:像上面一样的互斥锁),那么将其放入容器中可能是一个巨大的浪费,甚至是一个明显的错误。Boost 的开发人员足够聪明,意识到了这一点,并使他们的互斥锁不可复制,但并不是每个内部或第三方开发人员都会为每个对象想得那么周到(有些人可能需要昂贵的副本)。 - T.E.D.
我承认GMan的“一般情况”可能与我的非常不同。 :-) - T.E.D.
显示剩余4条评论

0

在我看来,std::map 试图通过传递一个 const boost::shared_mutex& 来调用 boost::shared_mutex 的复制构造函数,但是没有这样的构造函数可用:

/usr/include/c++/4.4/bits/stl_pair.h:84: error: no matching function for call to ‘boost::shared_mutex::shared_mutex(const boost::shared_mutex&)’
/usr/include/boost/thread/pthread/shared_mutex.hpp:47: note: candidates are: boost::shared_mutex::shared_mutex()
/usr/include/boost/thread/pthread/shared_mutex.hpp:21: note:                 boost::shared_mutex::shared_mutex(boost::shared_mutex&)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接