Союз указателей текстурных данных в C ++ - PullRequest
2 голосов
/ 13 октября 2019

Я получаю данные текстуры из разных источников, где данные находятся либо в COM-указателе BYTE *, либо в ID3D11Texture2D. Таким образом, я попытался создать контейнер STL, который будет содержать коллекцию следующего типа объединения.

    _COM_SMARTPTR_TYPEDEF(ID3D11Texture2D, __uuidof(ID3D11Texture2D));

    union TextureData
    {
        ID3D11Texture2DPtr m_tex2D;
        BYTE* m_byte;
    };

Но когда я компилирую только вышеупомянутое объявление без использования типа объединения для контейнера STL, я вижу следующее предупреждение:

предупреждение C4624: '.... :: TextureData': деструктор был неявноопределяется как удаленный

Кто-нибудь, пожалуйста, дайте мне знать, что я должен беспокоиться об объявлении этого союза?

РЕДАКТИРОВАТЬ:

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

std::array< std::tuple<< DXGI_FORMAT, TextureData>>, 4>;

EDIT2:

Я обнаружил, что если я использую, как показано ниже, предупреждение не показывает:

    union TextureData
    {
        ID3D11Texture2D* m_tex2D;
        BYTE* m_byte;
    };

1 Ответ

1 голос
/ 13 октября 2019

Из документации объединения :

Если объединение содержит нестатический элемент данных с нетривиальной специальной функцией-членом (конструктор копирования / перемещения, копирование / перемещениеприсваивание или деструктор), эта функция по умолчанию удаляется в объединении и должна быть явно определена программистом.

Это правило имеет большой смысл, если вы помнитечто C ++ не отслеживает активный член объединения , поэтому, когда объединение разрушается, он не знает, деструктор какого члена вызывать. Конечно, если все члены имеют тривиальные деструкторы, это не имеет значения.

Из документации _COM_SMARTPTR_TYPEDEF :

На умный указатель обычно ссылается typedefопределение, предоставленное макросом _COM_SMARTPTR_TYPEDEF. Этот макрос берет имя интерфейса и IID и объявляет специализацию _com_ptr_t с именем интерфейса плюс суффикс Ptr.

Из источников _com_ptr_t:

    // If we still have an interface then Release() it. The interface
    // may be NULL if Detach() has previously been called, or if it was
    // never set.
    //
    ~_com_ptr_t() throw()
    {
        _Release();
    }

Как видите, _com_ptr_t имеет нетривиальный деструктор, поэтому вам нужно добавить явный деструктор в ваше объединение. Это одна из редких ситуаций, когда вам нужно вручную вызывать деструкторы на объектах. Примерно так:

    union TextureData
    {
        ID3D11Texture2DPtr m_tex2D;
        BYTE* m_byte;

        ~TextureData() {
            if (/* m_tex2D is the active member */)
                m_tex2D.~_com_ptr_t();
        }
    };

Обратите внимание, что поскольку TextureData не отслеживает своего активного участника, вам необходимо определить, активен ли m_text2D или нет самостоятельно.

Другой подход к вамможно использовать это использовать std::variant вместо необработанного объединения. В отличие от объединения, вариант действительно отслеживает активного участника («альтернатива») и вызывает соответствующий деструктор для вас.

...