0

ポインターを値で渡す場合とアドレスで渡す場合の両方で、hello() が呼び出されるのはなぜですか?

class MyObj
{
public:
    void hello()
    {
        printf("hello");
    }
};

void myfunc(void *ptr)
{
    // I want the device
    MyObj* ptr2 = static_cast<MyObj*>(ptr);
    ptr2->hello();
}

int main()
{
    MyObj thisobj;

    void *pointer_to_device = &thisobj;

    myfunc(pointer_to_device);
    myfunc(&pointer_to_device);


    return 0;
}

&pointer_to_device は何をしているのですか? それは奇妙であり、許可されるべきではありません。関数はポインターへのポインターを要求していません

私はMSVC2012を使用しています

4

4 に答える 4

2

myfunc(&pointer_to_device)未定義の動作が発生します。

MyObjwhen calling または insideのメンバーにアクセスしないため、おそらくうまくいくようですhello。これを実証するには、更新されたバージョンの同じプログラムを試してください。MyObj

class MyObj
{
    const char* str;
public:
    MyObj() : str("hello") {}
    void hello()
    {
        printf("%s\n", str);
    }
};
于 2013-09-05T19:46:14.520 に答える
2

あなたのコードは未定義の動作を示しています。

hello()非仮想クラスの非仮想メソッドであることに注意してください。コンパイラはメソッド呼び出しをやみくもに生成し、MyObj::hello()呼び出しに使用されるポインターにたまたまガベージが含まれているものを使用して生成し、 thisとして渡します。

ちなみに、これは、「オブジェクト」(そもそもオブジェクトではない) でメンバー変数にアクセスし始めると、特に厄介になります。

于 2013-09-05T19:48:11.650 に答える
0

への 2 番目の呼び出しのmyfunc動作は未定義です。これは、avoid**を a にキャストしてからMyObj*逆参照するためです。未定義の動作とは、正しく動作しているように見えることを含め、あらゆることが起こり得ることを意味します。

それは奇妙であり、許可されるべきではありません。関数はポインターへのポインターを要求していません

void*これは、何かを指すことができるポインタであるa を要求しています。 MyObj(最初のケースでは) または別のものvoid*(2 番目のケースでは) を指すことができるので、許可されています。次のようなことをしないのはあなたの責任ですそれ。そうしないと信頼できない場合は、void*and キャストをいじらないでください。

コードが機能しているように見える理由は、オブジェクトのメンバー データにアクセスしないためです。そのため、コンパイラは実際に でメモリを読み取る必要はありません*ptr2。あなたのプログラムはこれとほぼ同等です (これには未定義の動作がないことを除いて):

void hello(MyObj* unused)
{
  printf("hello");
}

void myfunc(void *ptr)
{
    // I want the device
    MyObj* ptr2 = static_cast<MyObj*>(ptr);
    hello(ptr2);
}

int main()
{
    MyObj thisobj;

    void *pointer_to_device = &thisobj;

    myfunc(pointer_to_device);
    myfunc(&pointer_to_device);
}

の値がptr2実際に使用されることはないので、問題なく動作することに注意してください。あなたのバージョンでは、ポインターは によって技術的に逆参照されますptr2->hello()が、実際には、コンパイラーはメンバー関数を呼び出すために変数を逆参照する必要はありません。ただし、まだ未定義の動作です。

于 2013-09-05T19:48:26.920 に答える
0

問題を隠しているのは void* ptr です。void* はポインターへのポインターを受け取ることができます。それを MyObj* に置き換えると、コンパイラは文句を言います。

于 2013-09-05T19:46:42.883 に答える