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 (cch
typu 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 const
typename**, 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ż
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla