2017-02-18 6 views
2

Чтобы уточнить, я не говорю о многопоточной среде. Я часто сталкиваюсь с ситуацией, когда мне приходится выделять некоторые ресурсы в функции init (и, следовательно, освобождать ресурс в функции завершения), и где я бы хотел избежать двойного вызова. Мне было интересно, есть ли что-то вроде встроенного ключевого слова в C/C++, чтобы сделать его вызываемым один раз. Что-то более сложное, чем статической локальной переменной, которую я бы дублируется во всех моих функций инициализации, какЕсть ли способ сделать глобальную функцию/статическую функцию-член вызываться один раз?

static bool isInitialized = false; 
if (!isInitialized) { 
    isInitialized = true; 
//... 
} 

Или, может быть, это не так уж плохо, и я мог бы скрыть это за макро CALLABLE_ONCE.

Я открыт для любых решений из C/C++ 03/C++ 11/C++ 14.

EDIT:

Причина, почему я бы с помощью инициализации/прекратить схему на глобальном масштабе будет в основном из-за того, что я склонен создавать пространство имен для объектов, которые не должно быть экземплярами более чем один раз, и избегать использования синглтона, как рекомендуется на this post. Конечно, использование класса было бы проще, так как я просто использовал бы конструктор/деструктор, но как можно инициализировать (только один раз) этот вид сущностей (пространств имен)?

+2

Есть ли что-то, препятствующее вам сделать это внутри конструктора/деструктора? – Telokis

+1

Я не знаю ни одного объекта в C++, который предоставляет эту функциональность. В Windows вы можете воспользоваться возможностями [Одноразовая инициализация] (https://msdn.microsoft.com/en-us/library/ms686934.aspx). – IInspectable

+0

@Ninetainedo Да, я ищу что-то, что работает в глобальной функции/статической функции-члене. Если бы я использовал конструктор/деструктор, это в основном означало бы использовать какой-то одноэлемент. У меня может быть флаг участника, который говорит, что если я инициализирован во всех случаях, но я искал ключевое слово или взломал, передав лямбду функции. – lordjohncena

ответ

1

Существует std::call_once, хотя он представлен для использования с потоками, а не только с одним потоковым приложением. Он также может использоваться приложением с одним потоком.

Одна проблема, с которой вы можете столкнуться, - это если она выбрасывает, то она не считается инициализированной. Однако вы можете protect the initialization function с try/catch.

Также в вашем случае может потребоваться публичная статическая функция и другая функция, которая является частной. Публичная статическая функция будет выполнять std::call_once. Что-то вроде этого:

class my_class 
{ 
public: 
    static void init() 
    { 
    std::call_once(m_initialized, private_init); 
    } 

private: 
    static void private_init() 
    { 
    ... // init here 
    } 

    static std::once_flag m_initialized; 
}; 

Как вы можете видеть, это выглядит точно так же, как и ваша функция, за исключением того, что if() и флажковый скрыты. Вы также можете сохранить флаг m_initialized в своей первой функции как статическую переменную.

Единственное отличие состоит в том, что std::call_once является потокобезопасным.

+0

+1 и спасибо за выделение на std: : call_once, который можно использовать в приложении с одним потоком. Его также можно было бы использовать в моем случае. Но статическая локальная переменная инициализации в моем случае также потокобезопасна, как описано [здесь] (http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11)? Я опубликую редактирование, которое, надеюсь, объяснит, почему я ищу глобальные функции, совместимые с такими решениями. – lordjohncena

+0

@lordjohncena, статическая переменная сама будет инициализирована безопасно, так как C++ 11 (они знают, создавали ли вы потоки, так что это очень быстро, если у вас есть приложение с одним потоком.) Однако ваш 'if()' и 'var = true' потребуется мьютекс ...' std :: call_once() 'позаботится об этом для вас, если вы его используете. –

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

  • Нет связанных вопросов^_^