类包含Boost Concurrent Queue成员时vector resize触发GCC编译错误如何解决
错误触发原因
- 首先
boost::concurrent::sync_bounded_queue属于不可拷贝、不可移动的并发容器类型,它的拷贝构造、移动构造函数都被显式删除。你给Test类声明的默认移动构造Test(Test&&) = default,会因为成员变量_queue无法完成移动操作,被编译器隐式标记为删除。最终Test类本身也成为不可拷贝、不可移动的类型。 - 单参数
std::vector::resize()方法有两个隐含要求:扩容时如果需要重新分配内存,必须能将已有元素移动/拷贝到新内存块;新增的元素需要支持默认构造。由于Test类不可移动也不可拷贝,不满足vector的元素类型要求,因此触发编译期静态断言报错。
可行的解决方法
方法1:vector存储智能指针(最推荐)
将vector的元素类型改为std::unique_ptr<Test>,智能指针本身支持移动操作,同时能保证Test对象的生命周期和vector绑定,符合你需要统一管理对象生命周期的需求。修改后的代码示例:
#include <boost/thread/sync_bounded_queue.hpp> #include <thread> #include <vector> #include <memory> struct Test { Test() :_queue(1){} Test(const Test&) = delete; Test(Test&&) = delete; // 移动构造也可以直接删掉,不需要了 void hello(){} boost::concurrent::sync_bounded_queue<int> _queue; }; int main() { std::vector<std::unique_ptr<Test>> vec; vec.reserve(10); // 预分配指针的存储空间,避免后续重分配 for(size_t i = 0; i < 10; ++i) { vec.push_back(std::make_unique<Test>()); } for(size_t i = 0; i < 10; ++i) { std::thread t(&Test::hello, vec.at(i).get()); t.join(); } return 0; }
方法2:改用std::list存储对象
std::list是链表结构,插入元素时不需要迁移已有元素的内存地址,不需要元素支持移动/拷贝操作,可以直接存储Test类型的对象:
#include <boost/thread/sync_bounded_queue.hpp> #include <thread> #include <list> struct Test { Test() :_queue(1){} Test(const Test&) = delete; Test(Test&&) = delete; void hello(){} boost::concurrent::sync_bounded_queue<int> _queue; }; int main() { std::list<Test> test_list; for(size_t i = 0; i < 10; ++i) { test_list.emplace_back(); // 直接在链表节点上构造Test对象 } for(auto& item : test_list) { std::thread t(&Test::hello, &item); t.join(); } return 0; }
额外说明
你之前担心的栈上对象生命周期问题,在你给出的循环写法中其实不存在:因为你调用了t.join()会阻塞等待线程执行完毕再进入下一轮循环,test对象的生命周期完全覆盖线程运行周期,不会出现野指针问题。但如果你需要所有Test对象同时存活、或者需要线程 detach 后继续运行,还是建议用容器统一管理对象生命周期。
内容的提问来源于stack exchange,提问作者user997112
相关产品推荐
相关产品推荐

