Udostępnij za pośrednictwem


const i volatile, wskaźniki

Słowa kluczowe const i volatile zmieniają sposób traktowania wskaźników. Słowo const kluczowe określa, że nie można zmodyfikować wskaźnika po zainicjowaniu; wskaźnik jest chroniony przed modyfikacją.

Słowo volatile kluczowe określa, że wartość skojarzona z nazwą, którą następuje, może być modyfikowana przez akcje inne niż te w aplikacji użytkownika. volatile W związku z tym słowo kluczowe jest przydatne do deklarowania obiektów w pamięci udostępnionej, do których można uzyskać dostęp przez wiele procesów lub globalnych obszarów danych używanych do komunikacji z procedurami przerwania obsługi.

Gdy nazwa jest zadeklarowana jako volatile, kompilator ponownie ładuje wartość z pamięci za każdym razem, gdy jest on uzyskiwany przez program. Zmniejsza to znacznie możliwości optymalizacji. Jednakże, gdy stan obiektu może ulegać nieoczekiwanym zmianom, jest to jedyny sposób zapewnienia przewidywalnej wydajności programu.

Aby zadeklarować obiekt wskazywany przez wskaźnik jako const lub volatile, użyj deklaracji formularza:

const char *cpch;
volatile char *vpch;

Aby zadeklarować wartość wskaźnika — czyli rzeczywisty adres przechowywany w wskaźniku — jako const lub volatile, użyj deklaracji formularza:

char * const pchc;
char * volatile pchv;

Język C++ uniemożliwia przypisanie, które umożliwiłyby modyfikację obiektu lub wskaźnika zadeklarowanego jako const. Takie przypisania powodowałyby usunięcie informacji, z którą obiekt lub wskaźnik został zadeklarowany, naruszając w ten sposób zamiar pierwotnej deklaracji. Rozważ następujące deklaracje:

const char cch = 'A';
char ch = 'B';

Biorąc pod uwagę powyższe deklaracje dwóch obiektów (cchtypu const char i ch, typu char), następujące deklaracje/inicjowanie są prawidłowe:

const char *pch1 = &cch;
const char *const pch4 = &cch;
const char *pch5 = &ch;
char *pch6 = &ch;
char *const pch7 = &ch;
const char *const pch8 = &ch;

Poniższa deklaracja/inicjacje są błędne.

char *pch2 = &cch;   // Error
char *const pch3 = &cch;   // Error

Deklaracja pch2 deklaruje wskaźnik, dzięki któremu można zmodyfikować obiekt stały i dlatego jest niedozwolona. Deklaracja pch3 określa, że wskaźnik jest stały, a nie obiekt; deklaracja jest niedozwolona z tego samego powodu pch2 , że deklaracja jest niedozwolona.

Poniższe osiem przypisań pokazuje przypisania poprzez wskaźnik i zmianę wartości wskaźnika dla wcześniejszych deklaracji; na chwilę obecną załóżmy, że inicjalizacja pch1 poprzez pch8 była poprawna.

*pch1 = 'A';  // Error: object declared const
pch1 = &ch;   // OK: pointer not declared const
*pch2 = 'A';  // OK: normal pointer
pch2 = &ch;   // OK: normal pointer
*pch3 = 'A';  // OK: object not declared const
pch3 = &ch;   // Error: pointer declared const
*pch4 = 'A';  // Error: object declared const
pch4 = &ch;   // Error: pointer declared const

Wskaźniki zadeklarowane jako volatile, lub jako kombinacja const i volatile, przestrzegają tych samych reguł.

Wskaźniki do const obiektów są często używane w deklaracjach funkcji w następujący sposób:

errno_t strcpy_s( char *strDestination, size_t numberOfElements, const char *strSource );

Poprzednia instrukcja deklaruje funkcję, strcpy_s, gdzie dwa z trzech argumentów są wskaźnikiem typu .char Ponieważ argumenty są przekazywane przez odwołanie, a nie przez wartość, funkcja będzie mogła modyfikować zarówno, strDestination jak i strSource , jeśli strSource nie zostały zadeklarowane jako const. Deklaracja strSource funkcji zapewnia const obiekt wywołujący, którego strSource nie można zmienić przez wywołaną funkcję.

Uwaga

Ponieważ istnieje standardowa konwersja z typename na consttypename**, jest legalna przekazanie argumentu typu char * do strcpy_s. Jednak odwrotność nie jest prawdziwa; nie istnieje niejawna konwersja w celu usunięcia atrybutu const z obiektu lub wskaźnika.

Wskaźnik const danego typu można przypisać do wskaźnika tego samego typu. Jednak wskaźnik, którego nie const można przypisać do const wskaźnika. Poniższy kod pokazuje poprawne i niepoprawne przypisania:

// const_pointer.cpp
int *const cpObject = 0;
int *pObject;

int main() {
pObject = cpObject;
cpObject = pObject;   // C3892
}

Poniższy przykład pokazuje sposób deklarowania obiektu jako const, jeśli posiadasz wskaźnik do wskaźnika do obiektu.

// const_pointer2.cpp
struct X {
   X(int i) : m_i(i) { }
   int m_i;
};

int main() {
   // correct
   const X cx(10);
   const X * pcx = &cx;
   const X ** ppcx = &pcx;

   // also correct
   X const cx2(20);
   X const * pcx2 = &cx2;
   X const ** ppcx2 = &pcx2;
}

Zobacz też

Wskaźniki pierwotne