无法将std::mutex与std::vector配合使用的编译错误排查
编译错误:
std::mutex导致类无法被std::vector::push_back处理 问题代码
#include <vector> #include <mutex> class A { public: A(){}; private: std::mutex a_mutex; }; int main() { std::vector<A> v; A a; v.push_back(a); return 0; }
编译错误信息
$ g++ test__use_of_deleted_function.cpp In file included from /usr/include/c++/8/x86_64-redhat-linux/bits/c++allocator.h:33, from /usr/include/c++/8/bits/allocator.h:46, from /usr/include/c++/8/string:41, from test__use_of_delete_function.cpp:1: /usr/include/c++/8/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = A; _Args = {const A&}; _Tp = A]’: /usr/include/c++/8/bits/alloc_traits.h:475:4: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = A; _Args = {const A&}; _Tp = A; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<A>]’: /usr/include/c++/8/bits/stl_vector.h:1079:30: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = A; _Alloc = std::allocator<A>; std::vector<_Tp, _Alloc>::value_type = A]’: test__use_of_delete_function.cpp:19:17: required from here /usr/include/c++/8/ext/new_allocator.h:136:4: error: use of deleted function ‘A::A(const A&)’ { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test__use_of_delete_function.cpp:6:7: note: ‘A::A(const A&)’ is implicitly deleted because the default definition would be ill-formed: class A ^ test__use_of_delete_function.cpp:6:7: error: use of deleted function ‘std::mutex::mutex(const std::mutex&)’ In file included from /usr/include/c++/8/mutex:43, from test__use_of_delete_function.cpp:3: /usr/include/c++/8/bits/std_mutex.h:97:5: note: declared here mutex(const mutex&) = delete; ^~~~~ In file included from /usr/include/c++/8/vector:62, from test__use_of_delete_function.cpp:2: /usr/include/c++/8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = A; _Args = {A}]’: /usr/include/c++/8/bits/stl_uninitialized.h:83:18: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*; bool _TrivialValueTypes = false]’: /usr/include/c++/8/bits/stl_uninitialized.h:134:15: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*]’: /usr/include/c++/8/bits/stl_uninitialized.h:289:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*; _Tp = A]’: /usr/include/c++/8/bits/stl_uninitialized.h:311:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = A*; _ForwardIterator = A*; _Allocator = std::allocator<A>]’: /usr/include/c++/8/bits/vector.tcc:447:6: required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const A&}; _Tp = A; _Alloc = std::allocator<A>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<A*, std::vector<A> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = A*]’: /usr/include/c++/8/bits/stl_vector.h:1085:4: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = A; _Alloc = std::allocator<A>; std::vector<_Tp, _Alloc>::value_type = A]’: test__use_of_delete_function.cpp:19:17: required from here /usr/include/c++/8/bits/stl_construct.h:75:7: error: use of deleted function ‘A::A(A&&)’ { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); } ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test__use_of_delete_function.cpp:6:7: note: ‘A::A(A&&)’ is implicitly deleted because the default definition would be ill-formed: class A ^ test__use_of_delete_function.cpp:6:7: error: use of deleted function ‘std::mutex::mutex(const std::mutex&)’ In file included from /usr/include/c++/8/mutex:43, from test__use_of_delete_function.cpp:3: /usr/include/c++/8/bits/std_mutex.h:97:5: note: declared here mutex(const mutex&) = delete; ^~~~~
错误原因
std::mutex的拷贝构造函数被显式删除(mutex(const mutex&) = delete;),C++编译器原本会为类自动生成默认的拷贝/移动构造函数,但如果类成员包含不可拷贝/移动的对象,编译器会隐式删除类的默认拷贝构造函数和移动构造函数。
当调用std::vector::push_back(const A&)时,需要拷贝A对象到容器中,但A的拷贝构造函数已被删除,因此触发编译错误。
解决方案
方案1:在容器中存储智能指针(推荐)
指针可以被拷贝,而std::mutex属于对象本身,不会被拷贝,同时智能指针能自动管理内存,避免泄漏:
#include <vector> #include <mutex> #include <memory> class A { public: A(){}; private: std::mutex a_mutex; }; int main() { std::vector<std::unique_ptr<A>> v; // 直接在容器内构造对象 v.push_back(std::make_unique<A>()); // 或者转移外部对象的所有权 // auto a = std::make_unique<A>(); // v.push_back(std::move(a)); return 0; }
如果需要共享对象所有权,可以使用std::shared_ptr替代std::unique_ptr。
方案2:直接在容器内构造对象
使用emplace_back直接在容器内存中构造A对象,完全避免拷贝/移动操作:
#include <vector> #include <mutex> class A { public: A(){}; private: std::mutex a_mutex; }; int main() { std::vector<A> v; // 直接在vector的内存空间中构造A对象 v.emplace_back(); return 0; }
这种方式适用于不需要先创建外部对象的场景。
方案3:手动实现类A的拷贝/移动构造函数(不推荐)
由于std::mutex不能被拷贝,需要为拷贝构造函数创建新的互斥锁,需确保逻辑符合业务需求:
#include <vector> #include <mutex> class A { public: A(){}; // 拷贝构造:为新对象创建独立的mutex A(const A&) : a_mutex() {} // 移动构造:同样需要手动实现,因为mutex不可移动 A(A&&) noexcept : a_mutex() {} private: std::mutex a_mutex; }; int main() { std::vector<A> v; A a; v.push_back(a); return 0; }
注意:拷贝后的对象拥有独立互斥锁,若你的业务逻辑需要共享锁,这种方式会引发线程安全问题。
内容的提问来源于stack exchange,提问作者user180574
相关产品推荐
相关产品推荐

