Maison >développement back-end >C++ >Pourquoi mes objets OpenGL dans les classes C RAII cessent-ils de fonctionner après la copie ?
Objets OpenGL dans les classes C RAII : pourquoi ils cessent de fonctionner après la copie
En C, il est courant d'utiliser RAII (l'acquisition de ressources est l'initialisation ) pour garantir que les objets sont automatiquement nettoyés lors de leur destruction. Cependant, lorsqu'il s'agit d'objets OpenGL, il est crucial de comprendre comment le modèle RAII affecte l'utilisation des objets.
Considérez la classe suivante qui encapsule un objet tampon OpenGL :
class BufferObject { private: GLuint buff_; public: BufferObject() { glGenBuffers(1, &buff_); } ~BufferObject() { glDeleteBuffers(1, &buff_); }
Initialement, cette classe semble fonctionner correctement. Cependant, des problèmes surviennent lors de l'exécution de certaines opérations :
vector<BufferObject> bufVec; { BufferObject some_buffer; // Initialize some_buffer; bufVec.push_back(some_buffer); } bufVec.back(); // buffer doesn't work. BufferObject InitBuffer() { BufferObject buff; // Do stuff with `buff` return buff; } auto buff = InitBuffer(); // Returned buffer doesn't work.
La copie de la classe via des instructions push_back ou return provoque des erreurs OpenGL inattendues. Pour comprendre pourquoi, il est nécessaire de se plonger dans les mécanismes de RAII.
Lorsqu'un objet est copié, le constructeur de copie par défaut est invoqué (en supposant qu'il en existe un). Dans ce cas, un constructeur de copie par défaut copie simplement les variables membres. Cependant, cette copie inclut le handle d'objet OpenGL (buff_), qui est unique à chaque objet.
Le problème survient lorsque l'objet d'origine est détruit (à la fin de la première portée dans notre exemple). Le destructeur tente de supprimer l'objet OpenGL, qui a déjà été copié par le ou les nouveaux objets. Cet objet OpenGL orphelin ne peut plus être utilisé et entraîne des erreurs.
Pour résoudre ce problème, il est crucial de définir une copie personnalisée et une sémantique de déplacement pour les wrappers d'objet OpenGL. Cette approche garantit que la référence de l'objet OpenGL est correctement transférée entre les objets sans provoquer de conflits.
Déplacer un objet implique de transférer la propriété de ses ressources vers un autre objet. Au lieu de copier, les ressources de l'objet sont affectées au nouvel objet et l'objet d'origine reste dans un état valide mais vide. Cette approche évite les conflits potentiels et garantit que l'objet OpenGL reste valide.
Dans la classe BufferObject modifiée ci-dessous, le constructeur de copie et l'opérateur d'affectation de copie sont supprimés et la sémantique de déplacement est implémentée :
class BufferObject { private: GLuint buff_; public: BufferObject() { glGenBuffers(1, &buff_); } BufferObject(const BufferObject& other) = delete; BufferObject& operator=(const BufferObject& other) = delete; BufferObject(BufferObject&& other) : buff_(other.buff_) { other.buff_ = 0; } BufferObject& operator=(BufferObject&& other) { if (this != &other) { Release(); buff_ = other.buff_; other.buff_ = 0; } return *this; } ~BufferObject() { Release(); } void Release() { if (buff_) glDeleteBuffers(1, &buff_); } };
En implémentant la sémantique de déplacement, il est possible de créer des wrappers RAII de déplacement uniquement pour les objets OpenGL. Cette approche permet une gestion sûre et efficace des objets OpenGL en C .
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!