Перейти к содержанию
    

Объекты в C++

Всем привет!

 

Подскажите, пожалуйста, в каком порядке создаются глобальные объекты программы (экземпляры классов и переменные простых типов)?

В том, в котором они перечислены при объявлении?

Компилятор WinAVR.

Имеет ли значение вид компилятора C++?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Порядок вызова глобальных конструкторов не регламентирован.

 

Т. е., получается, что мы не знаем, какой объект создастся первым, а какой последним? А если, к примеру, объект 2 зависит от объекта 1 и объект 1 должен быть создан до объекта 2 (применительно к классам)?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Именно, даже существуют методики, которые гарантируют что обьект А будет создан раньше обьекта Б. А вообще, если у вас сильная зависимость между классами, то возможно, следует пересмотреть иерархию классов.

 

Чтоб не быть голословным, вот пример:

 

class SomeFoo {
    public:
        int func1() { ... };
};

/* функция возвращает ссылку на обьект типа SomeFoo */
SomeFoo& some_func()
{
    /* статически создаем обьект типа SomeFoo */
    static SomeFoo myClass;
    
    /* возвращаем ссылку на статический обьект */
    return myClass;
}

class SomeOtherClass {
    public:
        my_other_func() {
            int some_value = some_func().func1();
        };
};

 

надеюсь из кода все понятно. Общий смысл в том, что в функции создается статический объект, ссылка на который, потом возвращается туда куда нам надо. Мне такой трюк нужен был только однажды, да и то, потом как-то обошлось, поменял немного архитектуру.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в каком порядке создаются глобальные объекты программы
В том порядке, в котором линкер сложит секции *(.ctors*). В пределах одной единицы компиляции получаются в порядке объявления. Между единицами компиляции - можно сортировать по имени файла, можно еще по каким-то признакам (точно не помню). Все это описывается строкой скрипта KEEP(SORT(*)(.ctors)). Описание - (в том числе и сортировок) - в документации на линкер директива SORT(). Но все это нестандандартно и от лукавого, закладываться на это - делать код неперносимым на другой компилятор. Нужна ли такая переносимость если gcc есть под все процы с которыми работаете - решать вам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Фактически, ситуация следующая (возможно, посоветуете что-нибудь лучше).

Допустим, в проекте есть несколько глобальных переменных, которые используются в нескольких модулях.

Мы преследуем две цели: задать порядок создания и облегчить включение глобальных переменных в несколько модулей.

Создаем "x.cpp", в котором определяем все наши глобальные объекты, в файле "x.hpp" объявляем все эти объекты, используя директиву "extern". Далее инклудим файл "x.hpp" в нужные нам .cpp.

 

Но все это нестандандартно и от лукавого

 

Понимаю теперь, будем от этого уходить :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Фактически, ситуация следующая (возможно, посоветуете что-нибудь лучше).

Допустим, в проекте есть несколько глобальных переменных, которые используются в нескольких модулях.

Мы преследуем две цели: задать порядок создания и облегчить включение глобальных переменных в несколько модулей.

Создаем "x.cpp", в котором определяем все наши глобальные объекты, в файле "x.hpp" объявляем все эти объекты, используя директиву "extern". Далее инклудим файл "x.hpp" в нужные нам .cpp.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

singleton гарантирует, что объект будет создан только один раз и мы сами должны вызвать его Instance в нужном месте и в нужное время. Таким образом это не есть глобальный объект в обычном понимании, конструктор которого компилятор сам помещает в специальную таблицу, обеспечивая вызов конструкторов до main().

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Общий смысл в том, что в функции создается статический объект, ссылка на который, потом возвращается туда куда нам надо.
Всё так, только инициализируется этот объект именно в момент вызова функции (собственно, для гарантии наличия, функция-то может вызываться и из других конструкторов), что тянет за собой дополнительную флаговую переменную со смыслом bool initialised; и соответствующий код. А при отсутствии (это я уже о gcc) -fno-threadsafe-statics там ещё и мьютексы __cxa_guard_*

В мелких мелкоконтроллерах жаба давить начинает.

Мне такой трюк нужен был только однажды, да и то, потом как-то обошлось, поменял немного архитектуру.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

singleton гарантирует, что объект будет создан только один раз и мы сами должны вызвать его Instance в нужном месте и в нужное время. Таким образом это не есть глобальный объект в обычном понимании, конструктор которого компилятор сам помещает в специальную таблицу, обеспечивая вызов конструкторов до main().

Конечно. Это просто один из путей обхода проблем, возникающих от неопределенности порядка создания объектов, объявленных в разных единицах трансляции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...