68

C++ は、コンパイル ユニット (.cpp ファイル) 内の変数が宣言順に初期化されることを保証します。コンパイル単位の数について、このルールはそれぞれ個別に機能します (クラス外の静的変数を意味します)。

ただし、変数の初期化の順序は、異なるコンパイル単位では定義されていません。

gcc と MSVC のこの順序に関する説明はどこで見ることができますか (これに依存するのは非常に悪い考えであることはわかっています。これは、新しい GCC メジャーと異なる OS に移行するときにレガシー コードで発生する可能性がある問題を理解するためのものです)。 ?

4

7 に答える 7

76

あなたが言うように、順序は異なるコンパイル単位間で定義されていません。

同じコンパイル単位内では、順序が明確に定義されています。つまり、定義と同じ順序です。

これは、これが言語レベルではなく、リンカ レベルで解決されるためです。そのため、リンカーのドキュメントを確認する必要があります。これが何らかの有用な方法で役立つとは思えませんが。

gcc の場合: ldを確認してください

リンクされているオブジェクト ファイルの順序を変更しても、初期化の順序が変わる可能性があることがわかりました。したがって、心配する必要があるのはリンカーだけではなく、ビルド システムによってリンカーが呼び出される方法です。問題を解決しようとしても、実際には初心者ではありません。

これは通常、独自の初期化中に相互に参照するグローバルを初期化する場合にのみ問題になります (そのため、コンストラクタを持つオブジェクトにのみ影響します)。

問題を回避するためのテクニックがあります。


  • 注 1: グローバル:
    の前に初期化される可能性がある静的ストレージ期間変数を参照するために大まかに使用されますmain()
  • 注 2:
    一般的なケースでは、メインの前に静的ストレージ期間変数が初期化されることが期待されますが、コンパイラは状況によっては初期化を延期することができます (ルールは複雑で、詳細については標準を参照してください)。
于 2008-10-17T07:23:14.840 に答える
20

モジュール間のコンストラクターの順序は、主にオブジェクトをリンカーに渡す順序の関数であると思います。

ただし、GCC では、グローバル ctorの順序を明示的に指定するために使用できます。init_priority

class Thingy
{
public:
    Thingy(char*p) {printf(p);}
};

Thingy a("A");
Thingy b("B");
Thingy c("C");

期待どおり「ABC」を出力しますが、

Thingy a __attribute__((init_priority(300))) ("A");
Thingy b __attribute__((init_priority(200))) ("B");
Thingy c __attribute__((init_priority(400))) ("C");

「BAC」を出力します。

于 2008-10-17T07:30:16.870 に答える
4

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12-このリンクは動き回っています。これはより安定しいますが、周りを見回す必要があります。

編集:osgxはより良いリンクを提供しました。

于 2008-10-17T07:41:03.323 に答える
1

C の背景を持つ Martin のコメントに加えて、私は常に静的変数をプログラムの実行可能ファイルの一部と考え、データ セグメントに組み込まれて割り当てられたスペースを考えます。したがって、静的変数は、コードが実行される前に、プログラムのロード時に初期化されると考えることができます。これが発生する正確な順序は、リンカーによって出力されたマップ ファイルのデータ セグメントを調べることで確認できますが、ほとんどの意図と目的では、初期化は同時に行われます。

編集:静的オブジェクトの構築順序によっては、移植性が低くなる可能性があり、おそらく避けるべきです。

于 2008-10-17T07:38:10.193 に答える
0

最終的な順序を本当に知りたい場合は、コンストラクターが現在のタイムスタンプをログに記録するクラスを作成し、各 cpp ファイルにクラスの静的インスタンスをいくつか作成して、初期化の最終的な順序を知ることができるようにすることをお勧めします。各ファイルのタイムスタンプが同じにならないように、コンストラクターに少し時間のかかる操作を入れてください。

于 2015-04-25T09:54:38.260 に答える