13

コードサンプルは物事を説明する必要があります:

class A
{
    B* pB;
    C* pC;
    D d;

    public : 
    A(int i, int j) : d(j)
    {
        pC = new C(i, "abc");
    } // note pB is not initialised, e.g. pB(NULL)

    ...
};

明らかに、pB は安全 (かつ明確) にするために明示的に NULL に初期化する必要がありますが、現状では、A の構築後の pB の値は何ですか? デフォルトで初期化されているか(ゼロですか?)、そうでないか(つまり、不確定で、メモリにあるものは何でも)です。C++ での初期化にはかなりのルールがあることを認識しています。

デフォルトで初期化されていないと思います。Visual Studio でデバッグ モードで実行すると、pB が 0xcdcdcdcd を指すように設定されます。これは、メモリが (ヒープ上で) 新規作成されたが、初期化されていないことを意味します。ただし、リリース モードでは、pB は常に NULL を指します。これはたまたまなので、当てにならないのでしょうか。または、これらのコンパイラは私のためにそれを初期化していますか (標準に含まれていなくても)? また、Solaris で Sun のコンパイラを使用してコンパイルすると、NULL になるようです。

私は、標準への特定の参照を本当に探しています。

ありがとう。

4

7 に答える 7

12

これは、標準からの関連する一節です。

12.6.2 ベースとメンバーの初期化 [class.base.init]

4 与えられた非静的データメンバーまたは基底クラスが
mem-initializer-list の mem-initializer-idによって命名されていない場合、

-- エンティティが (おそらく cv 修飾された) クラス型 (またはその配列) または基本クラスの非静的データ メンバーであり、エンティティ クラスが非 POD クラスである場合、エンティティはデフォルトで初期化されます ( dcl.init)。エンティティが const 修飾された型の非静的データ メンバーである場合、エンティティ クラスには、ユーザーが宣言した既定のコンストラクターが必要です。

--それ以外の場合、エンティティは初期化されません。エンティティが const 修飾された型または参照型、または (直接的または間接的に) const 修飾された型のメンバーを含む (おそらく cv 修飾された) POD クラス型 (またはその配列) である場合、プログラムは形が悪い。

クラス X のコンストラクターへの呼び出しが完了した後、メンバーが

of X がコンストラクターの mem-initializers で指定されておらず、
デフォルトで初期化されておらず
、コンストラクターの本体の実行中に初期化されていない場合、メンバーの値は不確定です。

于 2009-07-17T16:35:38.670 に答える
4

C++0x 標準セクション 12.6.2.4 によると、ポインター変数の場合、それを初期化リストに含めず、コンストラクターの本体に設定しないと、不確定になります。価値。0xCDCDCDCD と 0 は、他の値と同様に 2 つの可能な値です。:-)

于 2009-07-17T16:40:32.170 に答える
1

これは、割り当てられたメモリに何が含まれているかを期待できなかった古き良き C 時代の成果物だと思います。標準が C++ に移行するにつれて、この「規則」は維持されました。C++ コンパイラが開発されるにつれて、個々の作成者はこの問題を「修正」することにしました。したがって、マイレージは、選択したコンパイラによって異なる場合があります。

「0xcdcdcdcd」は、コードのデバッグに「役立つ」簡単に識別できるパターンのようです。そのため、リリース モードでは表示されません。

これが少しでもお役に立てば幸いです。

于 2009-07-17T16:22:17.497 に答える
1

初期化されていないポインターは、基本的にランダムな値を含むことができますが、一部のコンパイラーは、特にデバッグ モードで、それらを 0 またはその他の認識可能な値で埋める傾向があります。

私見ですが、これは C++ の「使わないものにはお金を払わない」設計によるものです。重要ではない場合、コンパイラは変数を初期化する費用を負担する必要はありません。もちろん、ランダムなポインターを追跡したら、次回はそれを初期化するのが賢明だと思うかもしれません...

于 2009-07-17T16:37:03.973 に答える
0

初期化されていないポインターは、何でも指すことができます。一部のコンパイラ ベンダーは、0 や 0xcdcdcdcd などを指すようにしてくれます。

コードが安全で移植可能であることを確認するには、常にポインターを初期化する必要があります。0 または有効な値に設定します。

例えば

C* pc = 0;

また

C* pc = new C(...);

ポインタを常に 0 に初期化する場合、これは安全です。

if (!pc) 
    pc = new C(...);

初期化しないと、初期化されたポインターと初期化されていないポインターを区別する方法がありません。

余談ですが、C++ には NULL のようなキーワードはありません。ほとんどのコンパイラは NULL を 0 として定義しますが、それを使用する移植性は考慮されていません。新しい c++0x 標準では、新しいキーワード nullptr が導入されるため、それが登場すると、最終的に移植可能な null ポインター定数が得られます。

于 2009-07-17T16:26:12.997 に答える
0

使用している言語について何も学ばないことをお勧めすることはめったにありませんが、この場合、pB が初期化されているかどうかは有用な情報ではありません。初期化するだけです。自動的に初期化される場合、コンパイラは余分な初期化を最適化します。そうでない場合は、プロセッサ命令を 1 つ追加して、多数の潜在的なバグを防いだことになります。

于 2009-07-17T17:20:49.173 に答える
0

pB の値は定義されていません。一貫して同じ値である場合とそうでない場合があります。通常、A の特定のインスタンスが割り当てられる前にメモリ内の同じ場所に何があったかによって異なります。

于 2009-07-17T16:26:20.437 に答える