如何在不销毁对象的前提下将对象从一个vector移至另一个vector?
如何在非渲染线程将GPU资源对象从vector中间移至另一个vector末尾?
我有一个存储GPU资源对象的vector,这些对象只能在特定渲染线程中安全创建或销毁,但现在需要在非渲染线程里把它们从一个vector的中间位置移到另一个vector的末尾。
为了安全,我已经删除了该类的拷贝构造、拷贝赋值和移动赋值运算符,只保留了移动构造函数。请问有没有办法实现这个移动操作,且不会销毁任何对象?
相关代码如下:
class MappedBuffer { public: MappedBuffer(GLuint name, char * mapping) : m_name(name), m_mapping(mapping) { assert(std::this_thread::get_id() == RENDER_THREAD_ID); }; MappedBuffer(MappedBuffer && other) : m_name(other.m_name), m_mapping(other.m_mapping) { other.m_name = 0; other.m_mapping = 0; } MappedBuffer(const MappedBuffer & other) =delete; MappedBuffer & operator=(MappedBuffer && other) =delete; MappedBuffer & operator=(const MappedBuffer & other) =delete; ~MappedBuffer() { assert(m_name == 0 || std::this_thread::get_id() == RENDER_THREAD_ID); if (m_name) { gl::buffer::unmap(m_name); gl::buffer::dealloc(m_name); } } private: char * m_mapping {0}; // 直接指向GPU内存 GLuint m_name {0}; }; // 非渲染线程 int f(size_t srcIndex, std::vector<MappedBuffer> & src, std::vector<MappedBuffer> & dest) { // 如何实现类似下面的操作,但不销毁任何对象? // dest.push_back(src.begin() + srcIndex); // dest.erase(src.begin() + srcIndex); }
解决方案
可以通过std::move结合vector的emplace_back和erase方法实现,核心是利用移动构造函数转移资源所有权,同时让原位置对象处于空状态(不会触发GPU资源销毁)。
修改后的f函数代码如下:
// 非渲染线程 int f(size_t srcIndex, std::vector<MappedBuffer> & src, std::vector<MappedBuffer> & dest) { // 边界检查,避免越界访问 if (srcIndex >= src.size()) { return -1; // 返回错误码表示操作失败 } // 用std::move将原对象转为右值,触发移动构造,转移资源所有权 dest.emplace_back(std::move(src[srcIndex])); // 擦除原位置的空对象,此时对象m_name为0,析构不会执行GPU资源释放 src.erase(src.begin() + srcIndex); return 0; // 操作成功返回0 }
原理说明
std::move(src[srcIndex])将原对象转换为右值引用,调用MappedBuffer的移动构造函数,把GPU资源的所有权转移到dest的新对象中,同时将原对象的m_name和m_mapping置为0。- 原位置的对象此时处于“空”状态,调用
src.erase触发析构时,因为m_name为0,析构函数里的GPU资源释放逻辑不会执行,完全符合线程安全要求。 - 整个过程仅转移资源所有权,没有拷贝、创建或销毁GPU资源,完全满足你的需求。
内容的提问来源于stack exchange,提问作者Anne Quinn
相关产品推荐
相关产品推荐

