質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1021閲覧

コピーコンストラクタでデストラクタの発生を防ぐ方法

退会済みユーザー

退会済みユーザー

総合スコア0

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/10/15 02:23

編集2021/10/15 03:00

提示コードのMode.cppのprocessMesh()関数の戻り値でMeshクラスを返しているのですがそこでコピーコンストラクタが動きprocessNode()関数でmesh変数に.push_backされる際にデストラクタが動いてしまい。Shaderクラスのデストラクタが動いてしまい。変数が廃棄されてしまいます。これを防ぐにはどうすればいいのでしょうか?一様コメントアウトすると動きますが廃棄するという機能を廃棄したくありません。

#####試したこと
コメントアウトすると問題無く動く。

Shader.cpp
// ##################################### デストラクタ ##################################### FrameWork::Shader::~Shader() { printf("Shader デストラクタ\n"); glDeleteProgram(program); }
Mode.cpp
void FrameWork::D3::Model::processNode(aiNode *node, const aiScene *scene) { for(unsigned int i = 0; i< node->mNumMeshes; i++) { //printf("push_back\n"); aiMesh *m = scene->mMeshes[node->mMeshes[i]]; mesh.push_back(processMesh(m,scene)); } for(unsigned int i = 0; i< node->mNumChildren; i++) { //printf("再帰的\n"); processNode(node->mChildren[i],scene); } } void FrameWork::D3::Model::loadModel(const char *path) { Assimp::Importer import; //const aiScene *scene = import.ReadFile(path,aiProcess_Triangulate); const aiScene *scene = import.ReadFile(path,aiProcess_Triangulate | aiProcess_FlipUVs); if(scene == NULL) { std::cerr<<"ERROR::ASIMP: " << import.GetErrorString() <<std::endl; assert(0); } std::string str(path); directory = str.substr(0,str.find_last_of('/')); processNode(scene->mRootNode, scene); } FrameWork::D3::Mesh FrameWork::D3::Model::processMesh(aiMesh *m, const aiScene *scene) { // data to fill std::vector<VertexAttribute> ver(0); std::vector<unsigned int> idx(0); std::vector<Texture> tex(0); for(unsigned int i = 0; i < m->mNumVertices; i++) { VertexAttribute vert; glm::vec3 vector; vert.position[0] = m->mVertices[i].x; vert.position[1] = m->mVertices[i].y; vert.position[2] = m->mVertices[i].z; // normals if (m->HasNormals() == true) { //vert.normal[0] = m->mNormals[i].x; //vert.normal[1] = m->mNormals[i].y; //vert.normal[2] = m->mNormals[i].z; } // texture coordinates if(m->mTextureCoords != NULL) { glm::vec2 vec; //vert.uv[0] = m->mTextureCoords[0][i].x; //vert.uv[1] = m->mTextureCoords[0][i].y; /* // tangent vector.x = m->mTangents[i].x; vector.y = m->mTangents[i].y; vector.z = m->mTangents[i].z; //vert.Tangent = vector; // bitangent vector.x = m->mBitangents[i].x; vector.y = m->mBitangents[i].y; vector.z = m->mBitangents[i].z; //vert.Bitangent = vector; */ } else { //vert.uv[0] = 0.0f; //vert.uv[1] = 0.0f; } ver.push_back(vert); } /* for(unsigned int i = 0; i < m->mNumFaces; i++) { aiFace face = m->mFaces[i]; for(unsigned int j = 0; j < face.mNumIndices; j++) { idx.push_back(face.mIndices[j]); } } */ /* printf("ああ %d\n",m->mMaterialIndex); // process materials aiMaterial* material = scene->mMaterials[m->mMaterialIndex]; printf("いいい \n"); // 1. diffuse maps std::vector<Texture> diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse"); tex.insert(tex.end(), diffuseMaps.begin(), diffuseMaps.end()); // 2. specular maps std::vector<Texture> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular"); tex.insert(tex.end(), specularMaps.begin(), specularMaps.end()); // 3. normal maps std::vector<Texture> normalMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, "texture_normal"); tex.insert(tex.end(), normalMaps.begin(), normalMaps.end()); // 4. height maps std::vector<Texture> heightMaps = loadMaterialTextures(material, aiTextureType_AMBIENT, "texture_height"); tex.insert(tex.end(), heightMaps.begin(), heightMaps.end()); // return a mesh object created from the extracted mesh data */ return Mesh(ver, idx, tex); }
Mesh.cpp
FrameWork::D3::Mesh::Mesh(std::vector<VertexAttribute> ver, std::vector<unsigned int> idx, std::vector<Texture> tex) : Transform() { this->vertex = ver; //頂点 this->index = idx; //インデックス this->texture = tex; //テクスチャ printf("this->vertex: %d\n",this->vertex.size()); printf("this->index: %d\n",this->index.size()); printf("this->texture: %d\n\n",this->texture.size()); if ( shader.Input(FrameWork::LoadShader("Shader/3D/BasicMono_3D.vert")->data(), FrameWork::LoadShader("Shader/3D/BasicMono_3D.frag")->data()) == false) { printf("シェーダーロード失敗\n"); } glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); //glBufferData(GL_ELEMENT_ARRAY_BUFFER, index.size() * sizeof(unsigned int),index.data(), GL_DYNAMIC_DRAW); glBufferData(GL_ARRAY_BUFFER, vertex.size() * sizeof(VertexAttribute), vertex.data(), GL_DYNAMIC_DRAW); GLint attrib = shader.getAttribLocation("vertexPosition"); glEnableVertexAttribArray(attrib); glVertexAttribPointer(attrib, 1, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); shader.setBindAttribLocation("vertexPosition"); //printf("あああ\n"); // vertex texture coords //attrib = shader.getAttribLocation("vertexUV"); //glEnableVertexAttribArray(attrib); //glVertexAttribPointer(attrib, 2, GL_FLOAT, GL_FALSE, sizeof(VertexAttribute), (void*)(sizeof(GLfloat) * 3)); //printf("ららら\n"); // vertex normals //attrib = shader.getAttribLocation("vertexNormal"); //glEnableVertexAttribArray(attrib); //glVertexAttribPointer(attrib, 3, GL_FLOAT, GL_FALSE, sizeof(VertexAttribute), (void*)(sizeof(GLfloat) * 5)); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); } void FrameWork::D3::Mesh::Draw() { shader.setEnable(); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VertexAttribute) * vertex.size(), vertex.data()); //Transform setPosition(glm::vec3(0,0,-20)); //座標 setScale(glm::vec3(10,10,10)); //スケール setRotate(glm::vec3(0,0,0),0); //回転 //描画 shader.setUniformMatrix4fv("uTranslate",getMatTranslation()); shader.setUniformMatrix4fv("uRotate", getMatRotate()); shader.setUniformMatrix4fv("uScale", getMatScale()); shader.setUniform4f("uFragment", FrameWork::GetGlColor(glm::vec4(0,0,255,255))); shader.setUniformMatrix4fv("uViewProjection", FrameWork::Camera::getViewProjection()); for(unsigned int i = 0; i < texture.size(); i++) { //glBindTexture(GL_TEXTURE_2D, texture[i].id); //glActiveTexture(GL_TEXTURE0 + i); } //glDrawElements(GL_TRIANGLES, index.size(), GL_UNSIGNED_INT, 0); glDrawArrays(GL_TRIANGLES,0,vertex.size()); //バインド解除 glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); //glBindTexture(GL_TEXTURE_2D, 0); shader.setDisable(); }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

どうすればいいのでしょうか?

  • 「そういう重要なブツの寿命を握っているようなやつを,そもそもコピー可能な型とすべきなのか?」

というあたりから……かな?
でも,コピー不可とするなら,そのように安直にvectorにpush_backだとかできなくなるから,
オブジェクトをいつ生成していつまで保持するのか? どのような形に保持するのか? 等を見直す必要が生じ得るから,結構なコード変更になるかもしれない.

  • デストラクタ内に条件分岐でも(e.g. 参照カウントみたいな)入れて,問題の処理自体を「やるか やらないか」みたく制御を行うことも考えられるかもしれない.
  • そもそもそのような重要なブツの寿命を握る場所を今とは別の場所に変えてしまえば,直面している問題自体が消滅するのかもしれない.

投稿2021/10/15 03:14

fana

総合スコア11996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2021/10/15 04:03 編集

Mesh とかいう型のインスタンスの寿命 と シェーダプログラム関係を扱っていると思われるブツの寿命 とが同一である,というのが,外野からは「???」って感じ. Mesh └shader Mesh └shader Mesh └shader みたいな関係になっているように見えるが,どちらかと言えば, shader ├Mesh ├Mesh … └Mesh 的な関係たるべきなのでは.
guest

0

インスタンスをコピーしたらオリジナルとコピーの両方でデストラクタが呼ばれるのは避けられません。Shader クラスのように何かリソース開放する責任があるクラスは、原則コピー不可にすべきです。

std::vectorに入れたいときは std::unique_ptrstd::shared_ptr などスマートポインタを入れます。

(ということを以前にも書いた気がします)

投稿2021/10/15 03:10

編集2021/10/15 03:34
int32_t

総合スコア21695

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問