はいいいえ:はい2回呼び出され、2つの異なるオブジェクトでは呼び出されません。
のヨーヨーが原因A.cppとB.cppは両方dfinitializer
のローカルおよび独立したコピーを持っていますの#includeの
// A.cpp
#include "datafile.h"
...
と
// B.cpp
#include "datafile.h"
...
があるとしましょう。
datafile.cppは、nifty_counter
(最初の0の値... static int nifty_counter = 0;
)とCDatafile :: mSome(ファイルレベルで初期化した方がよい)を定義しています。
どのようなCDataFileInitializer
ctorは、即時に作成され破棄された一時的なCSomeClass()が既に初期化されたに割り当てられます。
実際、CDataFileが割り当て可能であるという理由だけで、間違った実装が正しいことをしています。
静的データメンバーを初期化するだけであれば、静的メンバー定義(注:定義、宣言ではない)を含むモジュール内の何かが、
CDataFileInitializer[0x406035] creation
CDataFileInitializer FIRST INITIALIZATION
CSome[0x40602c] default created
initializing A.cpp
CDataFileInitializer[0x406029] creation
initializing B.cpp
CDataFileInitializer[0x406025] creation
main
do something in a.ccp
do something in b.ccp
main return
CDataFileInitializer[0x406025] destruction
cleaning B.cpp
CDataFileInitializer[0x406029] destruction
cleaning A.cpp
CSome[0x40602c] destroyed
CDataFileInitializer[0x406035] destruction
CDataFileInitializer LAST DESTRUCTION
:モジュールはのは、次のような出力が得られますより良いトリック
//some.h
#ifndef SOME_H_INCLUDED
#define SOME_H_INCLUDED
#include<iostream>
class CSome
{
public:
CSome() { std::cout << "CSome["<<this<<"] default created" << std::endl; }
CSome(const CSome& s) { std::cout << "CSome["<<this<<"] created from ["<<&s<<"]" << std::endl; }
CSome& operator=(const CSome& s) { std::cout << "CSome["<<this<<"] assigned from ["<<&s<<"]" << std::endl; return *this; }
CSome(CSome&& s) { std::cout << "CSome["<<this<<"] created moving ["<<&s<<"]" << std::endl; }
CSome& operator=(CSome&& s) { std::cout << "CSome["<<this<<"] assigned moving ["<<&s<<"]" << std::endl; return *this; }
~CSome() { std::cout << "CSome["<<this<<"] destroyed" << std::endl; }
};
#endif // SOME_H_INCLUDED
//datafile.h
#ifndef DATAFILE_H_INCLUDED
#define DATAFILE_H_INCLUDED
#include "some.h"
class CDataFile
{
public:
protected:
static CSome mSome;
};
static class CDataFileInitializer
{
public:
CDataFileInitializer();
~CDataFileInitializer();
} datafileinitializer;
#endif // DATAFILE_H_INCLUDED
//datafile.cpp
#include "datafile.h"
#include <iostream>
static int nifty_counter = 0; //the one and only
CSome CDataFile::mSome; //define and initialize
CDataFileInitializer::CDataFileInitializer()
{
std::cout << "CDataFileInitializer["<<this<<"] creation"<< std::endl;
if(!nifty_counter++)
{
std::cout << "CDataFileInitializer FIRST INITIALIZATION"<< std::endl;
}
}
CDataFileInitializer::~CDataFileInitializer()
{
std::cout << "CDataFileInitializer["<<this<<"] destruction"<< std::endl;
if(!--nifty_counter)
{
std::cout << "CDataFileInitializer LAST DESTRUCTION"<< std::endl;
}
}
//A.cpp
#include <iostream>
static class A
{
public:
A() { std::cout << "initializing A.cpp" << std::endl; }
~A() { std::cout << "cleaning A.cpp" << std::endl; }
} a;
#include "datafile.h"
// other a.cpp code ...
void call_a() { std::cout << "do something in a.ccp" << std::endl; }
//B.cpp
#include <iostream>
static class B
{
public:
B() { std::cout << "initializing B.cpp" << std::endl; }
~B() { std::cout << "cleaning B.cpp" << std::endl; }
} b;
#include "datafile.h"
// other b.cpp code ...
void call_b() { std::cout << "do something in b.ccp" << std::endl; }
//main.cpp
#include <iostream>
void call_a();
void call_b();
int main()
{
std::cout << "main" << std::endl;
call_a();
call_b();
std::cout << "main return" << std::endl;
return 0;
}
を試してみましょう...
ので(ちょうど最適化することを避けるため)
コースのうち、アドレスはお使いのマシンによって異なり、実行されます。
これは気の利いたカウンターではありません。これは未定義の動作です。 – Mankarse
@Mankarse:なぜそれが定義されていないのか説明できますか? –
'CSomeClass CDataFile :: mSome'の動的初期化は、' dfinitializer'の動的初期化に関して不確定に配列されています。したがって、 'CDataFile :: mSome'で' operator = 'が呼び出されると、まだ構築されていないかもしれません。 – Mankarse