Compartilhar via


Ponteiros const e volatile

As palavras-chave const e volatile mudam o tratamento dos ponteiros. A palavra-chave const especifica que o ponteiro não pode ser alterado depois da inicialização; o ponteiro é protegido contra modificações posteriores.

A palavra-chave volatile especifica que o valor associado ao nome que segue pode ser alterado por ações diferentes daquelas do aplicativo do usuário. Portanto, a palavra-chave volatile é útil para declarar objetos na memória compartilhada que podem ser acessados por vários processos ou por áreas de dados globais usados na comunicação com rotinas de serviço de interrupção.

Quando um nome é declarado como volatile, o compilador recarrega o valor da memória sempre que é acessado pelo programa. Isso reduz drasticamente as otimizações possíveis. No entanto, quando o estado de um objeto pode ser alterado inesperadamente, é a única maneira de assegurar o desempenho previsível do programa.

Para declarar o objeto apontado pelo ponteiro como const ou volatile, use uma declaração da forma:

const char *cpch;
volatile char *vpch;

Para declarar o valor do ponteiro, ou seja, o endereço real armazenado no ponteiro, como const ou volatile, use uma declaração da forma:

char * const pchc;
char * volatile pchv;

A linguagem C++ impede as atribuições que permitiriam a alteração de um objeto ou um ponteiro declarado como const. Essas atribuições removeriam as informações com as quais o objeto ou o ponteiro foi declarado, violando assim a intenção da declaração original. Considere as seguintes declarações:

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

Dadas as declarações anteriores de dois objetos (cch, do const char, e ch, do tipo char ), as seguintes declarações/inicializações serão válidas:

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;

As seguintes declarações/inicializações são errôneas.

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

A declaração de pch2 declara um ponteiro em que um objeto constante pode ser modificado e, portanto, não é permitida. A declaração de pch3 especifica que é constante, não ao objeto; a declaração não é permitida pelo mesmo motivo que a declaração pch2 não é permitida.

As oito atribuições a seguir mostram a atribuição por ponteiro e a alteração do valor do ponteiro para as declarações anteriores; por enquanto, suponha que a inicialização estava correta para pch1 a pch8.

*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

Os ponteiros declarados como volatile, ou como uma mistura de const e volatile, obedecem às mesmas regras.

Os ponteiros para os objetos const são usados frequentemente em declarações de função como segue:

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

A instrução anterior declara uma função, strcpy_s, onde dois dos três argumentos são do tipo ponteiro para char. Como os argumentos são passados por referência e não por valor, a função é livre para alterar strDestination e strSource se strSource não for declarado como const. A declaração de strSource como const assegura que o strSource não possa ser alterado pela função chamada.

Observação

Como há uma conversão padrão de typename* em consttypename*, pode passar um argumento de tipo char * para strcpy_s. No entanto, o contrário não é válido; não há conversão implícita para remover o atributo const de um objeto ou ponteiro.

Um ponteiro const de determinado tipo pode ser atribuído a um ponteiro do mesmo tipo. No entanto, um ponteiro que não é const não pode ser atribuído a um ponteiro const. O código a seguir mostra atribuições corretas e incorretas:

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

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

O exemplo a seguir mostra como declarar um objeto como const se você tiver um ponteiro para um ponteiro para um objeto.

// 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;
}

Confira também

Ponteiros brutosde ponteiros