pin_ptr (C++/CLI)

Dichiara un puntatore di blocco, usato solo con Common Language Runtime.

Tutti i runtime

Non esistono note per questa funzionalità del linguaggio che si applichino a tutti i runtime.

Windows Runtime

Questa funzionalità del linguaggio non è supportata in Windows Runtime.

Common Language Runtime

Un puntatore di blocco è un puntatore interno che impedisce lo spostamento dell'oggetto puntato nell'heap sottoposto a Garbage Collection. Ciò significa che il valore di un puntatore di blocco non viene modificato da Common Language Runtime. Ciò è necessario quando si passa l'indirizzo di una classe gestita a una funzione non gestita, affinché l'indirizzo non cambi in modo imprevisto durante la risoluzione della chiamata della funzione non gestita.

Sintassi

[cli::]pin_ptr<cv_qualifiertype>var = &initializer;

Parametri

cv_qualifier
const o volatile qualificatori. Per impostazione predefinita, un puntatore di blocco è volatile. È ridondante ma non un errore per dichiarare un puntatore volatiledi blocco.

type
Tipo di initializer.

var
Nome della variabile pin_ptr.

initializer
Membro di un tipo di riferimento, elemento di una matrice gestita o qualsiasi altro oggetto che è possibile assegnare a un puntatore nativo.

Osservazioni:

Un oggetto pin_ptr rappresenta un superset delle funzionalità di un puntatore nativo. Qualsiasi elemento che può essere assegnato a un puntatore nativo può quindi essere assegnato anche a un oggetto pin_ptr. In un puntatore interno può essere eseguito lo stesso set di operazioni dei puntatori nativi, inclusi il confronto e l'aritmetica dei puntatori.

Un oggetto o un oggetto secondario di una classe gestita può essere bloccato e in questo caso Common Language Runtime non sposterà l'oggetto durante un'operazione di Garbage Collection. Lo scopo principale è quello di passare un puntatore ai dati gestiti come parametro effettivo di una chiamata di funzione non gestita. Durante un ciclo di raccolta, il runtime analizzerà i metadati creati per il puntatore di blocco e non sposterà l'elemento a cui puntano.

Bloccando un oggetto si bloccano anche i relativi campi valore, ovvero i campi di tipo valore o primitivo. I campi dichiarati dall'handle di rilevamento (%) non sono tuttavia bloccati.

Il blocco di un oggetto secondario definito in un oggetto gestito comporta il blocco di tutto l'oggetto.

Se il puntatore di blocco viene riassegnato per puntare a un nuovo valore, l'istanza a cui puntava in precedenza non viene più considerata bloccata.

Un oggetto è bloccato solo quando un elemento pin_ptr punta a esso. L'oggetto non è più bloccato quando il puntatore di blocco diventa esterno all'ambito o viene impostato su nullptr. Quando pin_ptr diventa esterno all'ambito, l'oggetto che era bloccato può essere spostato nell'heap dal Garbage Collector. I puntatori nativi che puntano ancora all'oggetto non vengono aggiornati e la dereferenziazione di uno di essi può generare un'eccezione irreversibile.

Se nessun puntatore di blocco punta all'oggetto (tutti i puntatori di blocco sono diventati esterni all'ambito, sono stati riassegnati in modo da puntare ad altri oggetti o sono stati impostati su nullptr), è garantito che l'oggetto non venga bloccato.

Un puntatore di blocco può puntare a un handle di riferimento, un handle di tipo valore o boxed, un membro di un tipo gestito o un elemento di una matrice gestita. Non può puntare a un tipo riferimento.

Se si accetta l'indirizzo di un oggetto pin_ptr che punta a un oggetto nativo, si verifica un comportamento indefinito.

I puntatori di blocco possono essere dichiarati solo come variabili locali non statiche nello stack.

I puntatori di blocco non possono essere usati come:

  • funzione (parametri)

  • tipo restituito di una funzione

  • membro di una classe

  • tipo di destinazione di un cast

pin_ptr si trova nello spazio dei nomi cli. Per altre informazioni, vedere Spazi dei nomi Platform, default e cli.

Per altre informazioni sui puntatori interni, vedere interior_ptr (C++/CLI).

Per altre informazioni sull'aggiunta di puntatori, vedere Procedura: Aggiungere puntatori e matrici e Procedura: Dichiarare puntatori di blocco e tipi di valore.

Requisiti

Opzione del compilatore: /clr

Esempi

L'esempio seguente usa pin_ptr per vincolare la posizione del primo elemento di una matrice.

// pin_ptr_1.cpp
// compile with: /clr
using namespace System;
#define SIZE 10

#pragma unmanaged
// native function that initializes an array
void native_function(int* p) {
   for(int i = 0 ; i < 10 ; i++)
    p[i] = i;
}
#pragma managed

public ref class A {
private:
   array<int>^ arr;   // CLR integer array

public:
   A() {
      arr = gcnew array<int>(SIZE);
   }

   void load() {
   pin_ptr<int> p = &arr[0];   // pin pointer to first element in arr
   int* np = p;   // pointer to the first element in arr
   native_function(np);   // pass pointer to native function
   }

   int sum() {
      int total = 0;
      for (int i = 0 ; i < SIZE ; i++)
         total += arr[i];
      return total;
   }
};

int main() {
   A^ a = gcnew A;
   a->load();   // initialize managed array using the native function
   Console::WriteLine(a->sum());
}
45

L'esempio seguente mostra che un puntatore interno può essere convertito in un puntatore di blocco e che il tipo restituito dell'operatore address-of (&) è un puntatore interno quando l'operando si trova nell'heap gestito.

// pin_ptr_2.cpp
// compile with: /clr
using namespace System;

ref struct G {
   G() : i(1) {}
   int i;
};

ref struct H {
   H() : j(2) {}
   int j;
};

int main() {
   G ^ g = gcnew G;   // g is a whole reference object pointer
   H ^ h = gcnew H;

   interior_ptr<int> l = &(g->i);   // l is interior pointer

   pin_ptr<int> k = &(h->j);   // k is a pinning interior pointer

   k = l;   // ok
   Console::WriteLine(*k);
};
1

L'esempio seguente mostra che è possibile eseguire il cast di un puntatore di blocco a un altro tipo.

// pin_ptr_3.cpp
// compile with: /clr
using namespace System;

ref class ManagedType {
public:
   int i;
};

int main() {
   ManagedType ^mt = gcnew ManagedType;
   pin_ptr<int> pt = &mt->i;
   *pt = 8;
   Console::WriteLine(mt->i);

   char *pc = ( char* ) pt;
   *pc = 255;
   Console::WriteLine(mt->i);
}
8
255