Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > C/C++: Прочее > обнуление статического вектора члена класса


Автор: rodion 29.08.21, 18:32
Есть класс типа фабрика. При регистрации классов всё нормально, а вот при создании вектор m_Patern оказывается пустым, при этом поле m_GenId сохраняет своё значение. Не подскажите в чём дело? Стандарт 2003.
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    class TInitTSourcesFunctor
    {
    public:
        TInitTSourcesFunctor()
        {
            TCreatorTran<TDG_TIME_COMPLEX, std::complex<double> >::Registration(
                new TBaseTransformationPatern<TDG_TIME_COMPLEX, TSourcesFunctor, int, std::complex<double> >);
        }
    };
    static TInitTSourcesFunctor init;


<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    template <TTypeDataOut TType, class TD>
    class TCreatorTran
    {
    public:
        const TTypeDataOut Type;
    public:
        TCreatorTran():
            Type(TType)
        {
            m_GenId += 0;
        }
     
        static unsigned GenId()
        {
            return ++m_GenId;
        }
     
        static void Registration(TBaseTransformation* a_T)
        {
            a_T->setId(GenId());
            m_Patern.push_back(a_T);
        }
        static TBaseTransformation* Create(unsigned a_Id)
        {
            std::vector<TBaseTransformation*>::iterator it = m_Patern.begin();
            for (; it != m_Patern.end(); ++it)
            {
                if ((*it)->Id() == a_Id)
                    return (*it)->Create();
            }
            return NULL;
        }
        static std::string  ChildName(unsigned a_Id)
        {
            std::string str;
            std::vector<TBaseTransformation*>::iterator it = m_Patern.begin();
            for (; it != m_Patern.end(); ++it)
            {
                if ((*it)->Id() == a_Id)
                    return (*it)->Name();
            }
            return str;
        }
     
        static unsigned MaxId()
        {
            return m_GenId;
        }
     
    private:
        TCreatorTran(const TCreatorTran &a_V);
        TCreatorTran& operator = (const TCreatorTran &a_V);
    private:
        static unsigned m_GenId;
        static std::vector<TBaseTransformation*> m_Patern;
    };

Автор: Qraizer 29.08.21, 21:34
По этим обрывкам наверняка сказать ничего нельзя. Предположу, что проблема в порядке инициализации статических объектов: порядок инициализации в пределах одной единицы трансляции определяется порядком определений объектов, порядок инициализации в разных единицах трансляции неопределён.
Похоже, что сначала инициализируется init, который вызывает TCreatorTran<>::Registration(), которая делает std::vector<>::push_back(), который чудесным образом не валит приложение в эксепшн на использовании неинициализированного объекта, и только потом отрабатывает конструктор по умолчанию(?) этого вектора TCreatorTran<>::m_Patern, который благополучно инициализирует объект, как и положено, пустым.

Добавлено
P.S. Т.к. TCreatorTran<> суть шаблон, то если он не инстаницирован явно, он и его статические элементы будут конкретизированы и инстанцированы неявно в точке инстанцирования. Таковая в подобной ситуации всегда будет после определения экземпляра TInitTSourcesFunctor, потому что только тут (?) впервые используется TCreatorTran<> с конкретными шаблонными аргументами.

Автор: rodion 01.09.21, 17:28
Спасибо, забыл что порядок создания статических объектов не определён.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)