2012-02-06 5 views
12

私はデフォルト-初期対値 - 初期の私の理解をリフレッシュし、this出くわした:なぜこの単純な割り当ては未定義の動作ですか?

struct C { 
    int x; 
    int y; 
    C() { } 
}; 

int main() { 
    C c = C(); 
} 

C(の場合は理由

どうやらこれはUBである)があり、 xおよびyメンバーを初期化することができるコンストラクタです。初期化は行われません。 C()をcにコピーしようとすると、未定義の動作が発生します。

私は理由を理解していると思いますが、私は確信していません。誰かが詳しく説明できますか?

これもUBですか?

int x; x = x; 

ちなみに、値の初期化に関しては、ゼロが保証されていますか?

int x = int(); 
+0

あなたは何を意味するのかよく分かりません。 xとyの値が初期化されていない場合はyesになりますが、コンストラクタがそれをしていないので、あなた自身の質問に答えています。 C c = C();私はそれが完全に有効だと思う。 – Sid

+0

誰かがそうでないと主張するまで、私はそれも完全に有効であると思った。私が読んでいるように、最初のスニペットはUBによってのみ可能で、2番目のスニペットもそうでなければ単純な初期化されていない値で、鼻のデーモンはありません。 – spraff

+2

@Sid:いいえ、初期化されていないオブジェクトの値を使用すると、未定義の動作が発生します。 –

答えて

13

あなたの最初の例では、デフォルトでは、コンパイラ 生成されたコピーコンストラクタがmemberwiseコピーを行いますので、int sが トラッピング値を有していてもよく、未定義の動作をしている、とトラッピング値を読み取るすることは、 プログラムがクラッシュする可能性がありますコピーします。

実際には、これは実際にこれが実際にクラッシュするとは想像できません。コンパイラ はほぼ確実にコピーアウトを最適化し、そうでない場合でも、 は、 トラップ値をチェックせずにコピーする特別なビット単位のコピーを使用します。 (C++では、 バイトをコピーできることが保証されています。)

もう1つのケースでは、未定義の動作です。この場合、 にはコピーの作成ではなく割り当てがありますが、コンパイラーは でそれを最適化する可能性は低くなります。 (最初の の例には割り当てがありません。コピーの作成のみです)

3番目の場合はyesです。空の親カテゴリを持つイニシャライザ( ユーザ定義のデフォルトイニシャライザはそれをオーバーライドしません)は、最初にゼロ( )の初期化を行います(静的有効期間を持つ変数とまったく同じです)。

+0

+1、一部のデバッグツールは、これを潜在的な問題として識別する(場合によっては)トラップする仮想マシンでアプリケーションを実行します。しかし、私は、実際のケースシナリオでは、初期化されていないメモリをコピーして移動する可能性があることに同意します。 –

+0

C++での参照は[dcl.init]/12 "です。評価で不確定な値が生成された場合の動作は、 の場合を除いて未定義です。" - このコードは大文字小文字の区別がありません –

-1

いいえ、ほとんどのコンパイラは変数の設定を最適化しますが、xの値は変更しません。次のコードと同じです。

int x = 0; 
x = 0; 

2行目は実行されません。何もしません。

+0

私のポストスニペットがUBの場合、コンパイラの最適化によって* any *の結果が生じる可能性があります。 – spraff

+3

私は、技術的に未設定値からの読み込みは未定義の動作であるとは反対します。コンパイラが読み込みを最適化するかどうかは、未定義の動作の可能な結果の* 1 *です。 –

1

cの値はunspecified valuesですが、これは実際にはundefined behaviorとは思われません。つまり、これらの指定されていない値を使用しない限り、プログラムの動作は明確に定義されています。それらを使用している場合、たとえばある条件で、またはそれらを印刷する場合、結果は定義されません。しかし、私はプログラムが変わったことをすることは許されていないと思う。ビルトインタイプ、これはこれもなしタイプのメンバーにまで及ぶなど、浮動小数点型の型のゼロ値、整数のすなわち00.0を得るために保証されている上、デフォルトのコンストラクタを使用してに関して

コンストラクタ。コンストラクタがあれば、自分でコンストラクタなしでメンバを構築する必要があります。

+1

Ooh、あなたはまっすぐな銃撃戦でジェームス・カンゼ対対決!彼は、コピーコンストラクタが初期化されていない値を「使用」し、そのことがUBであると述べています。あなたはそう言います。 –

+0

@SteveJessopしかし、この答えはより正しいようですね。 :)、+1 –

+0

@ Mr.Anubis:初期化されていない値でC++でできることは、最高レベルで不一致があるようです。規格には、左辺値変換を実行できないというテキストがありますが、(他のオブジェクト表現と共通して)それを 'unsigned char'としてアクセスできると思う人もいます。実際には、生成されたコピー管理者がデータを盲目的にコピーすること以外は何もしませんが、安全にプレーするためには、標準が許すものについてJamesが正しいと私は信じています。例えば、もしコピーが間違っていれば、intが何かを持っていればパリティビットを偶然にチェックすることができる。 –

関連する問題