2016-06-28 3 views
0

У меня есть что-то вроде этого:Где объекты, созданные при передаче параметров, должны быть удалены?

class GLSLShader { 
    public: 
     GLSLShader(GLenum); 
     ~GLSLShader(); 
}; 

class GLSLProgram { 
    public: 
     GLSLProgram(GLSLShader *, GLSLShader *); 
     ~GLSLProgram(); 

    private: 
     GLSLShader *m_VertexShader; 
     GLSLShader *m_FragmentShader; 
}; 

GLSLProgram конструктор собирается назвать так:

GLSLProgram program(new GLSLShader(GL_VERTEX_SHADER), new GLSLShader(GL_FRAGMENT_SHADER)); 

Мой вопрос, где я должен удалить выделенные объекты Shader. Должен ли я удалить его в деструкторе GLSLProgram или мне нужно управлять им по-другому с помощью кода ниже?

GLSLShader *vertex = new GLSLShader(GL_VERTEX_SHADER); 
GLSLShader *fragment = new GLSLShader(GL_FRAGMENT_SHADER); 
GLSLProgram program(vertex, fragment); 
delete vertex; 
delete fragment; 
+2

[Использование RAII] (http://stackoverflow.com/questions/395123/raii-and-smart-pointers-in-c) – Rakete1111

+1

@ Rakete1111: Он использует RAII. Деструктор GLSLShader очистит ресурсы, которые выделяет конструктор. Он просто использует RAII * очень плохо * –

+2

Речь идет о ** собственности **. Если вы предполагаете, что GLSLProgram является владельцем этих объектов, он должен удалить их при уничтожении. Если вы предполагаете, что GLSLProgram просто работает с ними, он не должен. – ilotXXI

ответ

2

У вас есть две основные проблемы.

Первой проблемой является неправильное использование объектов RAII. Точка объектов RAII предназначена для управления временем жизни объекта с использованием автоматических переменных, а не с использованием new и delete явно. Используя new на GLSLShader, не обертывая указатель на контейнер RAII, вы эффективно смягчаете работу, которую делают ваши деструкторы.

Ваш конструктор GLSLProgram не должен принимать объекты указателем. Он должен взять их на const&. Это позволяет абоненту решить, как долго эти объекты будут длиться.

Вторая проблема логична. Нет причин для того, чтобы GLSLProgram отвечал за уничтожение объектов шейдера, которые ему даны. Это должно быть до вызывающего кода, поскольку объекты шейдера GLSL могут быть повторно использованы.

Таким образом, GLSLProgram не должен пытаться уничтожить эти объекты. Но после успешного создания программы конструктор должен отсоединить шейдеры GLSL от программы GLSL с помощью glDetachShader.

В целом, ваш код должен выглядеть следующим образом:

GLSLShader vertex(GL_VERTEX_SHADER); 
GLSLShader fragment(GL_FRAGMENT_SHADER); 
//Fill `vertex` and `fragment` with actual shader code. 
GLSLProgram program(vertex, fragment); 
//Destructors for `vertex` and `fragment` will take care of themselves. 

Кроме того, вы должны знать о некоторых других вещах:

  1. Программа может быть создана с помощью более 2 объектов шейдерных , Поэтому у вас должны быть альтернативные конструкторы, которые могут принимать много таких объектов.

  2. Separable programs может быть создан непосредственно из строк, без использования шейдерных объектов.

+0

Следует ожидать, что я неправильно использовал RAII, так как не знал о его существовании. Я сомневался, что «GLSLProgram' должен нести ответственность за уничтожение шейдеров, поскольку, как вы сказали, их можно использовать повторно. Но другой вопрос: 'GLSLProgram' должен принимать их' const & ', но переменные-члены должны оставаться указателями? –

+0

И о других вещах, я знаю обо всех этих ситуациях. Я просто не дошел до его реализации. –

+1

@JeanCatanho: «* переменные-члены должны оставаться указателями *« Не должно быть переменных-членов для шейдеров; объект программы не должен * держать их * вообще. Он должен использовать их для связывания создаваемой программы, отсоединить шейдер после успешного создания программы и выйти. После того, как конструктор выполнил свою работу, он больше не нуждается в них. –

1

Должен ли я удалить его деструктор GLSLProgram или я должен управлять им по-разному

Это зависит от многого.

Нужно ли кому-либо кроме GLSLProgram получить доступ к этим динамическим объектам? Могут ли такие объекты переживать экземпляр GLSLProgram, который указывает на них? Если да для обоих, то память не может управляться только program.

В любом случае вы можете легко написать правильную программу, если вы делегируете управление памятью объекту RAII, который отвечает только за уничтожение динамического объекта.

С другой стороны, если GLSLProgram может управлять памятью исключительно, то, безусловно, также следует выделить их. Кроме того, по-видимому, нет причин использовать динамическое распределение вообще. Вместо этого я рекомендую использовать объекты-члены, если только не существует конкретной причины.

Учитывая попытки в этом вопросе, я предлагаю следующее:

class GLSLProgram { 
    public: 
     GLSLProgram(): 
      m_VertexShader(GL_VERTEX_SHADER), 
      m_FragmentShader(GL_FRAGMENT_SHADER) {} 

    private: 
     GLSLShader m_VertexShader; 
     GLSLShader m_FragmentShader; 
}; 
+0

Поскольку я не знал об RAII, я точно не знал, как с этим справиться, но, как вы сказали, возможно, нет причин вообще использовать динамическое размещение, даже если GLSLProgram не может управлять памятью исключительно. –

Смежные вопросы