2017-02-18 1 views
2

Um zu verdeutlichen, spreche ich nicht über Multi-Thread-Umgebung. Ich stoße oft auf eine Situation, in der ich einige Ressourcen in einer Init-Funktion zuweisen muss (und folglich die Ressource in einer Terminierungsfunktion freigebe) und wo ich es vermeiden möchte, sie zweimal aufzurufen. Ich habe mich gefragt, ob es in C/C++ etwas wie ein eingebautes Schlüsselwort gab, um es einmal aufrufbar zu machen. Etwas anspruchsvoller ist als ein statischer lokaler Variable, die ich über alle meine init Funktionen dupliziert haben würde wieGibt es eine Möglichkeit, die Funktion global/static member einmal aufrufbar zu machen?

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

Oder vielleicht ist es nicht so schlimm, und ich konnte dies hinter einem Makro CALLABLE_ONCE verstecken.

Ich bin offen für alle Lösungen von C/C++ 03/C++ 11/C++ 14.

EDIT:

Der Grund, warum ich das init/beenden Schema auf dem globalen Bereich aufgrund der Tatsache, wäre in erster Linie verwenden, dass ich Namespaces für Entitäten erstellen neigen, die nicht mehr instanziiert werden soll als einmal und vermeide die Verwendung von Singleton, wie unter this post empfohlen. Natürlich wäre die Verwendung einer Klasse einfacher, da ich einfach den Konstruktor/Destruktor verwenden würde, aber wie kann man diese Art von Entitäten (Namespaces) initialisieren (nur einmal)?

+2

Gibt es etwas, das Sie davon abhält, dies im Konstruktor/Destruktor zu tun? – Telokis

+1

Ich kenne keine Einrichtung in C++, die diese Funktionalität verfügbar macht. Unter Windows können Sie die Funktionen [Einmalige Initialisierung] (https://msdn.microsoft.com/de-de/library/ms686934.aspx) nutzen. – IInspectable

+0

@Ninetainedo Ja, ich suche nach etwas, das in einer globalen Funktion/statischen Elementfunktion funktioniert. Wenn ich einen Konstruktor/Destruktor verwenden würde, würde das bedeuten, dass ich einen Singleton irgendeiner Art verwenden muss. Ich könnte ein Mitglied Flag haben, das sagt, wenn ich in allen Fällen initialisiert werde, aber ich suchte nach einem Schlüsselwort oder einem Hack, indem ich ein Lambda zu einer Funktion übertrug. – lordjohncena

Antwort

1

Es gibt std::call_once, obwohl dargestellt, um mit Threads anstelle von nur einem Thread-Anwendung verwendet werden, kann es auch von einem One-Thread-Anwendung verwendet werden.

Das einzige Problem, das auftreten kann, ist, wenn es ausgelöst wird, dann wird es nicht als initialisiert betrachtet. Sie können jedoch protect the initialization function mit einem try/catch wenn erforderlich, obwohl.

Auch in Ihrem Fall möchten Sie vielleicht eine öffentliche statische Funktion und eine andere Funktion, die privat ist. Die öffentliche statische Funktion würde std::call_once ausführen. Etwas wie folgt aus:

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; 
}; 

Wie Sie sehen können, sieht es genau das gleiche wie Ihre Funktion, mit der Ausnahme, dass die if() und Flag-Schalter versteckt sind. Sie können auch das Flag m_initialized in Ihrer ersten Funktion als statische Variable beibehalten.

Der einzige Unterschied ist jedoch, dass die std::call_once Thread sicher ist.

+0

+1 und vielen Dank für das Highlight auf std: : call_once, das in einer One-Thread-App verwendet werden kann. Es könnte auch sehr gut in meinem Fall verwendet werden. Aber ist die statische lokale Variableninitialisierung in meinem Fall auch threadsicher wie [hier] erklärt (http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11)? Ich werde eine Bearbeitung veröffentlichen, die hoffentlich erklären wird, warum ich nach globalen Funktionen kompatible Lösungen wie diese suche. – lordjohncena

+0

@lordjohncena, die statische Variable selbst wird da C++ 11 auf sichere Weise initialisiert werden (sie wissen, ob Sie Threads erstellt, so ist es wirklich schnell, wenn Sie ein ein Thread App haben.) Aber die 'if()' und 'var = true' würde einen Mutex benötigen ... Das' std :: call_once() 'erledigt das für Sie, wenn Sie es benutzen. –

Verwandte Themen