2009-10-08 1 views
5

:コンストラクタを持っているか、初期化するコードを実行する必要があるC++の静的グローバルな非POD:理論と実践、私はQtのコーディング規則のドキュメントを読み、次の段落に出くわしました

何でも使用することができません(最初の使用時、ライブラリロード時、main()の前、またはでない場合は)、コンストラクタ/コードが実行されるときには定義されていないため、ライブラリコードのグローバルオブジェクトとして使用できます。共有ライブラリのイニシャライザの実行時間が定義されていても、そのコードをプラグインに移動するときや、ライブラリが静的にコンパイルされているときに問題が発生します。

私はtheoryのことを知っていますが、私は「全くありません」という部分を理解していません。時にはPOD以外のグローバル定数(QStringなど)を使用していて、初期化されていない可能性があります。これは共有オブジェクト/ DLL固有のものですか?これは壊れたコンパイラでのみ起こりますか?

このルールについてどう思いますか?

+0

QStringは、使用しないと初期化されないことがあります。しかし、それらを使用すると、初期化されます。これが使用の直前(つまり、mthodがオブジェクトに対して呼び出される直前)であっても。 –

答えて

8

「全くありません」という部分は、C++標準がこの問題について黙っていると言っています。共有ライブラリについては知らないので、特定のC++機能との相互作用については何も言及していません。

実際には、Windows、OSX、および多くのバージョンのLinuxや他のUnix(GUIとコマンドラインプログラムの両方)、プラグイン、およびスタンドアロンアプリケーションとして使用されるグローバルな非POD静的グローバルを見てきました。少なくとも1つのプロジェクト(非POD静的グローバルを使用したプロジェクト)は、これらのすべての組み合わせのフルセットのバージョンを持っていました。私が今までに見た唯一の問題は、ライブラリがアンロードされたときではなく、実行可能ファイルが停止したときに、ダイナミックライブラリ内のオブジェクトのdtorsを呼び出す非常に古いGCCバージョンを生成したということでした。もちろん、それは致命的でした(ライブラリーコードはライブラリーがすでに消えたときに呼び出されました)が、それは10年ほど前です。

もちろん、これはまだ何も保証しません。

2

私は静的オブジェクトのコンストラクタを省略することはできません。おそらく、スタティックライブラリは多くの場合、実行ファイルのトークンであるオブジェクトの束であり、それらが参照されている場合はであるという混乱があります。いくつかの静的オブジェクトは、オブジェクトを含むオブジェクトの外側で参照されないように設計されているため、オブジェクトファイルは、別の依存関係がある場合にのみ実行可能ファイルに格納されます。これは、いくつかのパターンでは当てはまりません(たとえば、それ自体を登録する静的オブジェクトを使用します)。

+0

私は静的オブジェクトと静的ライブラリを混同していると思います。 – sbi

+1

「静的オブジェクト」とは、「静的な記憶期間を持つオブジェクト」を意味しました。ところで、私は、初期化やデストラクタに副作用がある場合には削除できないというリファレンスを見つけました:3.7.1/2。 – AProgrammer

+0

私は静的ライブラリがここでは問題にならない可能性が高いことを意味しました。それは問題である動的ライブラリです。 – sbi

2

参照されないオブジェクトに静的オブジェクトが定義されている場合、リンカーは静的初期化コードを含め、オブジェクトを完全に整理することができます。 はlibsのために定期的に行う(gnuの下で、libcの部分を完全にリンクしていないなど)。

興味深いことに、これはライブラリ固有のものではないと思います。おそらく、メインビルドであってもオブジェクトで発生する可能性があります。

2

コンストラクタでグローバルオブジェクトを持つことに問題はありません。

コンストラクタ(またはデストラクタ)内の他のグローバルオブジェクトには依存しないでください。

しかし、依存関係がある場合、依存するオブジェクトは、同じコンパイル単位内にあるか、遅延評価されているため、使用する前に強制的に評価する必要があります。

コンストラクタ内のコードは、依存関係に関連していても全く同じではありませんが、実行されるタイミングに依存しないようにする必要がありますが、メソッドが呼び出されます)、C++は破壊順序がインスタンス化の逆であることを保証します。

これらのルールに固執することはそれ程難しくありません。

2

C++では、異なるコンパイル単位のオブジェクトに対して静的初期化子が実行する順序は定義されていません(順序はコンパイル単位内で明確に定義されています)。

2つの静的オブジェクトAとBが異なるコンパイル単位で定義されている状況を考えてみましょう。たとえば、オブジェクトBが初期化でオブジェクトAを実際に使用しているとします。

このシナリオでは、Bが最初に初期化され、初期化されていないAオブジェクトを呼び出す可能性があります。これは、「まったくではありません」という意味の1つではありません。たとえオブジェクトが最初に初期化される機会がないときに使用されています(後で初期化されたとしても)。

私は、ダイナミックリンクが、私がそのオブジェクトを初期化しないと思っていなかった複雑さを加えるかもしれないと思います。いずれにしても、静的なinitializatinoは、可能な限り避けるべき潜在的な問題を導入し、使用する必要がある場所では非常に注意深く取り扱わなければなりません。

関連する問題