Ich habe einige Objekte als global definiert, was bedeutet, dass ihr Konstruktor vor dem Programmstart oder unter DllMain() eingegeben werden. Dies verursacht einige Probleme, und deshalb möchte ich sie zu lokalen statischen verschieben.C++ 11 Magic Statik Workaround in Visual Studio 2012
Unser Hauptprojekt sind hauptsächlich unter Visual Studio 2012. Nach diesen Posts.
- “Magic static” singleton crashing when referenced in static destruction phase of another translation unit"
- Support For C++11/14/17 Features (Modern C++)
The Magic Statiken ist nicht in Visual Studio 2012 (bis VS 2015) umgesetzt. Daher ist die Initialisierung der lokalen statischen Variablen nicht automatisch vor dem gleichzeitigen Zugriff durch den Compiler geschützt.
Was ist eine geeignete Problemumgehung oder Lösung für diesen Fall?
Hier ist, was ich versucht:
eine Sperre hinzufügen zu schützen. Aber wenn die Variable initialisiert wird, bevor die Funktion eingegeben wird, kann mein Schloss unbrauchbar sein ...
// data object
struct Cat
{
Cat()
{
std::cout << __FUNCTION__ << "\n";
}
};
// lock mutex for singleton getter
static std::mutex getcat_m;
// singleton getter
Cat& GetCat(){
std::cout << __FUNCTION__ << " In\n";
std::lock_guard<std::mutex> lk(getcat_m);
static Cat cat;
std::cout << __FUNCTION__ << " Out\n";
return cat;
}
int main(int argc, char* argv[])
{
std::cout << __FUNCTION__ << " In\n";
Cat& cat = GetCat();
std::cout << __FUNCTION__ << " Out\n";
std::cin.ignore();
return 0;
}
Es zeigt tatsächlich wie erwartet. Der Konstruktor wird aufgerufen, nachdem die Funktion eingegeben wurde.
main In
GetCat In
Cat::Cat
GetCat Out
main Out
Aber ich bin mir nicht sicher, ob dies eine geeignete Lösung ist.
Sie können auch 'std :: call_once' ausprobieren. Sieht so aus, als wäre es auch empfehlenswert [18.2.4 Verwenden Sie std :: call_once anstelle des Double-Checked Locking-Patterns] (http://www.codingstandard.com/rule/18-2-4-use-stdcall_once-rather-than- das-doppelt-geprüfte-Sperrmuster /) –