5

次の2つのコードを比較してください。

1.1。

#include <iostream>
using namespace std;
class B{
public:
    int val;
};
int main(){
    B *b;
    int t = 0;
    b->val = 1;
    cout << 123 << endl;
    return 0;
}

2.2。

#include <iostream>
using namespace std;
class B{
public:
    int val;
};
int main(){
    B *b;
    b->val = 1;
    cout << 123 << endl;
    return 0;
}

どちらのバージョンもコンパイルされます。コード#1は正常に実行されますが、コード#2はランタイムエラーになります。

C ++ 11を使用してコンパイルし、Windowsマシンを実行しています。

それは本当に私を混乱させます。誰か教えてもらえますか?

4

5 に答える 5

14

どちらも間違っています。bポインタは初期化されていないため、ポインタを介してメモリにアクセスしないでください。

B *b;
b->val = 1;

ですから、そのうちの1つがクラッシュしたとき、あなたは幸運に恵まれました。

もう1つは運が悪かったのですが、クラッシュしませんでした。

修正

間接参照を削除できます...

B b;
b.val = 1;

または、割り当てることができます...

std::unique_ptr<B> b(new B());
b->val = 1;
于 2013-03-07T07:41:15.907 に答える
4

ここで初期化されていないポインタを逆参照しています

b->val = 1;

ポインタが指す場所は不明です。どこを指している可能性もあります。

このポインタに続くのは未定義動作(UB)です。これは、何が起こる可能性があるかを意味します。これは、あなたが見ているものです。

実際に起こっていることは、メモリのセグメントに、すべきではない値を書き込んでいるということです。そこに何があるかを知る方法はなく、C++標準は起こりうる結果について何の約束もできません。これを単にUBと呼びます。これらの状況を回避するのはあなた次第です。

于 2013-03-07T07:41:16.780 に答える
1

ポインタを使用する前に、ポインタを初期化する必要があります。 表示されるのは、いわゆる未定義動作です。

#include <iostream>
using namespace std;
class B{
public:
    int val;
};
int main(){
    B *b = new B();
    int t = 0;
    b->val = 1;
    cout << 123 << endl;
    delete b;
    return 0;
}

同様に動作するはずです

#include <iostream>
using namespace std;
class B{
public:
    int val;
};
int main(){
    B b;
    int t = 0;
    b.val = 1;
    cout << 123 << endl;
    return 0;
}
于 2013-03-07T07:42:36.170 に答える
1

問題は、初期化されていないポインタを使用していることです:B* b;。CおよびC++では、組み込み型は作成時に初期化されません。ジャンクを保持するだけです。

問題の解決策は簡単です。ポインタを使用しないでください。B b;クラスインスタンスを作成し、そのコンストラクターを呼び出します。

コード#1は正常に実行されますが、コード#2はランタイムエラーになります。

標準的な用語では、両方のコードは未定義の動作を示します。これは、ほとんど何でも起こり得ることを意味し、それは一見機能しているように見えます(つまり、エラーがあるかもしれませんが、目に見える症状はありません)。

于 2013-03-07T07:45:30.770 に答える
0

b->val無効なメモリ位置を指しています。b割り当てる前にメモリを割り当てますb->val

于 2013-03-07T07:42:44.530 に答える