ホームページ > バックエンド開発 > C++ > C RAII クラスの OpenGL オブジェクトがコピー後に動作しなくなるのはなぜですか?

C RAII クラスの OpenGL オブジェクトがコピー後に動作しなくなるのはなぜですか?

Barbara Streisand
リリース: 2024-11-26 19:14:09
オリジナル
656 人が閲覧しました

Why Do My OpenGL Objects in C   RAII Classes Stop Working After Copying?

C RAII クラスの OpenGL オブジェクト: コピー後に動作が停止する理由

C では、RAII (リソースの取得は初期化) を利用するのが一般的です) オブジェクトが破棄されたときに自動的にクリーンアップされるようにします。ただし、OpenGL オブジェクトを扱う場合、RAII パターンがオブジェクトの使用にどのような影響を与えるかを理解することが重要です。

OpenGL バッファ オブジェクトをカプセル化する次のクラスを考えてみましょう。

class BufferObject {
private:
  GLuint buff_;

public:
  BufferObject() { glGenBuffers(1, &buff_); }
  ~BufferObject() { glDeleteBuffers(1, &buff_); }
ログイン後にコピー

最初は、このクラス正しく機能しているようです。ただし、特定の操作を実行するときに問題が発生します。

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.
ログイン後にコピー

push_back または return ステートメントを介してクラスをコピーすると、予期しない OpenGL エラーが発生します。その理由を理解するには、RAII の仕組みを詳しく調べる必要があります。

オブジェクトがコピーされると、デフォルトのコピー コンストラクターが呼び出されます (コピー コンストラクターが存在すると仮定します)。この場合、デフォルトのコピー コンストラクターは単にメンバー変数をコピーします。ただし、このコピーには、各オブジェクトに固有の OpenGL オブジェクト ハンドル (buff_) が含まれています。

問題は、元のオブジェクトが破棄されるとき (この例では最初のスコープの最後) に発生します。デストラクターは、新しいオブジェクトによってすでにコピーされている OpenGL オブジェクトを削除しようとします。この孤立した OpenGL オブジェクトは使用できなくなり、エラーが発生します。

この問題を解決するには、OpenGL オブジェクト ラッパーのカスタム コピーおよび移動セマンティクスを定義することが重要です。このアプローチにより、競合を引き起こすことなく、OpenGL オブジェクト参照がオブジェクト間で適切に転送されることが保証されます。

オブジェクトの移動には、そのリソースの所有権を別のオブジェクトに転送することが含まれます。コピーする代わりに、オブジェクトのリソースが新しいオブジェクトに割り当てられ、元のオブジェクトは有効ですが空の状態のままになります。このアプローチにより、潜在的な競合が防止され、OpenGL オブジェクトが有効なままになります。

以下の変更された BufferObject クラスでは、コピー コンストラクターとコピー代入演算子が削除され、移動セマンティクスが実装されます。

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_);
  }
};
ログイン後にコピー

移動セマンティクスを実装することで、OpenGL オブジェクトの移動専用 RAII ラッパーを作成できます。このアプローチにより、C で OpenGL オブジェクトを安全かつ効率的に処理できるようになります。

以上がC RAII クラスの OpenGL オブジェクトがコピー後に動作しなくなるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート