Можно ли зарегистрировать функцию для запуска немедленно перед вводом main
? Я знаю, что все глобальные объекты создаются до ввода main
, поэтому я мог бы поместить код в конструктор глобального объекта, но это не гарантирует какой-либо определенный порядок. Что я хотел бы сделать, так это поместить код регистрации в конструктор, но, увы, я не знаю, что туда поместить :) Я предполагаю, что это сильно зависит от системы?
Вызов функции непосредственно перед main
Ответы (4)
Если вы используете gcc
, вы можете использовать атрибут constructor
для функции, чтобы она вызывалась до main
(см. документацию для более подробной информации).
constructor
destructor
Атрибут
constructor
вызывает автоматический вызов функции до того, как выполнение войдет вmain ()
. Точно так же атрибутdestructor
вызывает автоматический вызов функции после завершенияmain ()
или вызоваexit ()
. Функции с этими атрибутами полезны для инициализации данных, которые будут неявно использоваться во время выполнения программы.
Не уверен, что это именно то, что вы хотите... Но это должно сработать.
int main() {
static int foo = registerSomething();
}
Лучше явно вызывать такие функции регистрации либо в main, либо при первом доступе (но init при первом доступе может вызвать проблемы, если вы используете многопоточность).
registerSomething()
без статической переменной.
- person James McNellis; 07.03.2011
Я предполагаю здесь, но:
- Вы хотите зарегистрировать что-то в другой единице компиляции
- Вы столкнулись с проблемой регистрации, потому что глобальные переменные, в которые вы сохраняете регистрации, еще не созданы.
C++ определяет, что статическая функция инициализируется за некоторое время до первого обращения к ней, поэтому вы можете обойти это, как показано ниже.
typedef std::map<std::string, std::string> RegistrationCache;
RegistrationCache& get_string_map()
{
static RegistrationCache cache;
return cache;
}
class Registration
{
Registration(std::string name, std::string value)
{
get_string_map()[name] = value;
}
};
Цель
Допустим, вам нужно следующее:
STATIC_EXECUTE {
printf("This probably prints first"\n");
}
STATIC_EXECUTE {
printf("But order isn't guaranteed in the language spec, IIRC"\n");
}
int main(int argc, char **argv) {
printf("This definitely prints last. Buh Bye.\n");
}
Реализация
Версия C++ — статическая переменная + конструктор:
// This is some crazy magic that produces __StaticExecute__247
// Vanilla interpolation of __StaticExecute__##__LINE__ would produce __StaticExecute____LINE__
// I still can't figure out why it works, but it has to do with macro resolution ordering
// If you already have Boost, you can omit this part
#define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
#define BOOST_PP_CAT_I(a, b) BOOST_PP_CAT_II(~, a ## b)
#define BOOST_PP_CAT_II(p, res) res
// This avoids repeating the BOOST_PP_CAT 5X
#define STATIC_EXECUTE \
STATIC_EXECUTE_I(BOOST_PP_CAT(__StaticExecute__, __LINE__))
// This is the meat, a static instance of a class whose constructor runs your code
#define STATIC_EXECUTE_I(uniq_name) \
static struct uniq_name { \
uniq_name(); \
} BOOST_PP_CAT(uniq_name, __var); \
uniq_name::uniq_name() // followed by { ... }
Версия C — статическая переменная + функция
// ...
// The meat: a static variable initialized from a function call
#define STATIC_EXECUTE_I(uniq_name) \
static void uniq_name (); \
static int BOOST_PP_CAT(uniq_name, __var) = \
(uniq_name(), 0); \
static void uniq_name() // followed by { ... }
Примечания
ИМХО, версия C++ немного более элегантна. Теоретически он занимает немного меньше места. Иначе картошка, по-тат-ой.
Предостережение: я не тестировал версию "C" на правильном компиляторе только для C. Скрещенные пальцы; опубликуйте заметку, если это не сработает.
Предостережение: переносимость компилятора вообще сложная вещь. Я не был бы шокирован, если бы в каком-то другом компиляторе была ошибка.
Если вы пытаетесь понять магию Boost, обратите внимание, что (по крайней мере, для меня и в этом сценарии) также работает следующее:
#define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
#define BOOST_PP_CAT_I(a, b) a ## b
main
вmain()
, а затем создать вторую функцию,the_real_main()
, которая вызывается оттуда? Может быть, это обман. - person James McNellis   schedule 07.03.2011main
? - person RedX   schedule 07.03.2011