18

重複の可能性:
NULL クラス ポインターを介してクラス メソッドを呼び出す

#include <iostream>
using namespace std;
class test
{
    int i;
public:
    test():i(0){ cout << "ctor called" << endl;}
    void show()
    {
        cout<<"show fun called"<<endl;
    }
};

int main(int argc , char *argv[])
{
    test *ptr = NULL;
    ptr->show();
    return 0;
}

明らかに、ctor は呼び出されません。これは標準ですか?または、このポインターが show() メンバー関数で使用されていないため、コンパイラーの最適化だけですか?

4

4 に答える 4

36

メソッドを呼び出すためにポインタは必要ありません。ポインターの型がわかっているので、メソッドのコードもわかっています。メソッドは を使用しないためthis、コードは問題なく実行されます。これは未定義の動作ですが、ポインターが NULL かどうかをチェックしない方が効率的であるため、実行されます。

于 2012-07-04T00:07:29.937 に答える
10

アセンブリ (少なくとも 1 つのコンパイラについて) を見ると、なぜそれが実行されるのかがわかります (多くの人が指摘しているように未定義の動作ですが)。これらの 2 行の場合:

test *ptr = NULL;
ptr->show();

このアセンブリは生成されます (私が試したあるコンパイラで):

00000004: C7 45 FC 00 00 00  mov         dword ptr [ebp-4],0
          00
0000000B: 8B 4D FC           mov         ecx,dword ptr [ebp-4]
0000000E: E8 00 00 00 00     call        ?show@test@@QAEXXZ

メソッドのアドレスは実際のオブジェクト インスタンスから独立しているため、NULL (0) をスタックにプッシュし、メソッドを呼び出します。

于 2012-07-04T00:15:10.897 に答える
3

有効ではありません。動作は未定義であり、実際の結果はコンパイラによって異なります。

于 2012-07-04T00:08:08.257 に答える
1

まず、未定義の動作を引き起こすため、有効ではありません。あなたは本当にコンパイラがそれを許可する理由を尋ねています.答えは、それが実際のアプリケーションでは単に発生しない骨の折れるコードだからです.なぜわざわざ? 真の問題は、静的コード分析では予測できない方法でポインターが実行時に無効になる場合に発生します。

コンパイラはあなたの手を握るために存在するのではなく、標準に従ってコードをコンパイルするために存在します。それが有用な警告を提供する場合は素晴らしいですが、構文上または意味論的に違法なものは何もありません。未定義の動作を引き起こすコードを書いているだけです。

于 2012-07-04T00:09:42.033 に答える