Domanda

Devo scrivere il codice per una funzione di callback (verrà chiamata da ATL, ma non è molto importante):

HRESULT callback( void* myObjectVoid )
{
    if( myObjectVoid == 0 ) {
       return E_POINTER;
    }
    CMyClass* myObject = static_cast<CMyClass*>( myObjectVoid );
    return myObject->CallMethod();
}

ecco il void* è garantito che sia un puntatore a CMyClass, COSÌ static_cast è legale.La mia preoccupazione è che il codice debba essere il più portabile possibile (almeno nelle versioni più recenti di Visual C++).Quindi, per essere super paranoico, sono propenso a controllare il file CMyClass* puntatore - intendo, cosa succede se risulta essere nullo?

    if( myObjectVoid == 0 ) {
       return E_POINTER;
    }
    CMyClass* myObject = static_cast<CMyClass*>( myObjectVoid );
    if( myObject == 0 ) {
       return E_POINTER;
    }

Il secondo controllo è ragionevole?È possibile per static_cast trasformare un puntatore non nullo in un puntatore nullo?

È stato utile?

Soluzione

static_cast può cambiare il valore del puntatore, se si esegue il cast tra le parti degli oggetti su diversi offset:

class A{ int x; }; class B{ int y; };
class C : A,B {};

C *c=new C(); 

B *b=c; 
// The B part comes after the A part in C. Pointer adjusted

C *c2=static_cast<C*>(b); 
// Pointer gets adjusted back, points to the beginning of the C part

Tuttavia, "Il valore puntatore nullo (4.10) viene convertito nel valore del puntatore nullo del . Tipo di destinazione"(5.2.9-8), cioè se c è NULL, allora b è anche NULL (e non rettificati) e quindi c2 è impostato NULL L'intero mezzi cosa:. Se statico lanciando un non-NULL rendimenti myObjectVoid NULL, allora il valore di myObjectVoid è stato ottenuto eludere il sistema dei tipi in qualche modo. E significa, che il compilatore potrebbe buttare il secondo controllo via perché "non può accadere in ogni caso".

Altri suggerimenti

No. Se il puntatore si riferisce ad un oggetto valido, e la conversione è valido, allora il risultato sarà anche riferimento a un oggetto valido, quindi non sarà nullo. Se uno dei due non è valido, allora il codice non è corretto e il risultato è indefinito. Quindi l'unico modo per l'utilizzo valide per dare un risultato nullo è quello di iniziare con null.

Nel caso specifico di conversione tra puntatori all'oggetto e puntatori nulli, lo standard ha questo da dire (5.2.9 / 10):

  

Un valore di tipo "puntatore a oggetto" convertito "puntatore a void" e ritorna al tipo di puntatore originale avrà il suo valore originale.

e questo (4.10 / 3)

  

Il risultato di conversione di un "puntatore a T" ad un "puntatore a void" punta all'inizio della posizione di memoria in cui l'oggetto di tipo T risiede

così i puntatori di oggetto originale e finale sarà lo stesso, e il puntatore void sarà nullo se e solo se i puntatori sono oggetto.

L'unico cambiamento static_cast dovrebbe fare per un puntatore è per parola-allineamento. Quindi, in teoria, di myObjectVoid indicò l'ultimo byte in memoria, è possibile che potrebbe essere 'allineato-up" a 0, ma non vedo che come una preoccupazione realistica.

No, il secondo controllo non è ragionevole.Non è possibile per static_cast per trasformare un puntatore non nullo in un puntatore nullo.L'unica cosa static_cast potrebbe cambiare il valore fornito nel tuo caso (essendo un puntatore) è regolare l'indirizzo.Altrimenti si preoccupa strettamente di avvisare il resto dell'analisi del tipo del compilatore che il risultato dell'espressione dovrebbe essere trattato come il tipo di destinazione.Per un puntatore, ciò significa che il dereferenziamento trova l'indirizzo corretto all'interno dell'oggetto di destinazione e che i passi di incremento e decremento sono appropriati alla dimensione del tipo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top