Toutes ces opérations copient l'objet C++. Puisque votre classe n'a pas défini de constructeur de copie, vous obtenez le constructeur de copie généré par le compilateur. Cela copie simplement tous les membres de l'objet.
Tenir compte le premier exemple:
vector<BufferObject> bufVec;
{
BufferObject some_buffer;
//Initialize some_buffer;
bufVec.push_back(some_buffer);
}
bufVec.back(); //buffer doesn't work.
Lorsque vous appelez push_back
, il copie some_buffer
dans un BufferObject
dans le vector
. Donc, juste avant de quitter cette portée, il y a deux objets BufferObject
.
Mais quel objet tampon OpenGL stockent-ils? Eh bien, ils stockent le même. Après tout, en C++, nous avons juste copié un entier. Les deux objets C++ stockent donc la même valeur entière. Lorsque nous quittons cette portée, some_buffer
sera détruit. Par conséquent, il appellera glDeleteBuffers
sur cet objet OpenGL. Mais l'objet dans le vecteur aura toujours sa propre copie de ce nom d'objet OpenGL. Qui a été détruit.
Donc vous ne pouvez plus l'utiliser; d'où les erreurs.
La même chose se produit avec votre fonction InitBuffer
. buff
sera détruit après qu'il a été copié dans la valeur de retour, ce qui rend l'objet retourné sans valeur.
Tout cela est dû à une violation de la "règle de 3/5" en C++. Vous avez créé un destructeur sans créer de copier/déplacer des constructeurs/opérateurs d'affectation. C'est mauvais.
Pour résoudre ce problème, vos wrappers d'objets OpenGL doivent être des types à déplacement uniquement. Vous devez supprimer le constructeur de copie et de copie opérateur d'affectation, et fournir des équivalents de déplacement qui fixent le déplacé-d'un objet à 0:
class BufferObject
{
private:
GLuint buff_;
public:
BufferObject()
{
glGenBuffers(1, &buff_);
}
BufferObject(const BufferObject &) = delete;
BufferObject &operator=(const BufferObject &) = delete;
BufferObject(BufferObject &&other) : buff_(other.buff_)
{
other.buff_ = 0;
}
BufferObject &operator=(BufferObject &&other)
{
//ALWAYS check for self-assignment
if(this != &other)
{
Release();
buff_ = other.buff_;
other.buff_ = 0;
}
return *this;
}
~BufferObject() {Release();}
void Release();
{
if(buff_)
glDeleteBuffers(1, &buff_);
}
//Other members.
};
Il y a various other techniques pour faire des emballages de RAII déplacer uniquement pour les objets OpenGL.