Qualificadores de C ++ e especificadores de classe de armazenamento

Qualificadores de C ++ e especificadores de classe de armazenamento

CV significa constante-volátil. A declaração de um objeto que não é precedido por const e/ou volátil é do tipo CV-Unqualified. Por outro lado, a declaração de um objeto que é precedido por const e/ou volátil é um tipo qualificado por CV. Se um objeto for declarado const, o valor em sua localização não poderá ser alterado. Uma variável volátil é uma variável cujo valor está sob a influência do programador e, portanto, não pode ser alterado pelo compilador.Especificadores de classe de armazenamento se referem à vida, local e maneira pela qual existe um tipo. Os especificadores de classe de armazenamento são estáticos, mutáveis, thread_local e externo.

Este artigo explica qualificadores C ++ e especificadores de classe de armazenamento. Assim, algum conhecimento preliminar em C ++ é útil para realmente apreciar o artigo.

Conteúdo do artigo:

  • Qualificadores
  • Especificadores da classe de armazenamento
  • Conclusão

Qualificadores:

const

Um objeto declarado constante é um objeto O armazenamento (localização) de cujo valor não pode ser alterado. Por exemplo, na declaração:

int const theint = 5;

O valor de 5 no armazenamento para o seco não pode ser alterado.

volátil

Considere a seguinte declaração:

int portval = 26904873;

Os compiladores às vezes interferem no valor de uma variável com a esperança de otimizar o programa. O compilador pode manter o valor de uma variável como constante quando não deve ser constante. Os valores de objeto que têm a ver com portas de IO mapeadas de memória ou interromper rotinas de serviço de dispositivos periféricos podem ser interferidos pelo compilador. Para evitar essa interferência, faça a variável volátil, como:

int volátil portval;
Portval = 26904873;
ou como:
int volátil portval = 26904873;

Combinando const e volátil:

const e volátil podem ocorrer em uma declaração da seguinte forma:

int const volátil portval = 26904873;

qualificadores de CV

Uma variável precedida com const e/ou volátil é um tipo qualificado por CV. Uma variável não precedida com const ou volátil ou ambos é do tipo CV-Unqualified.

Encomenda:

Um tipo pode ser mais qualificado pelo CV do que outro:

  • Nenhum qualificador CV é menor que um qualificador const
  • Nenhum qualificador CV também é menor que um qualificador volátil
  • Nenhum qualificador CV é menor que um qualificador const-volátil
  • O qualificador const é menor que um qualificador const-volátil
  • Qualificador volátil é menor que um qualificador const-volátil

Ainda não foi concluído se const e volátil forem da mesma classificação.

Array e objeto instanciado:

Quando uma matriz é declarada constante, como na declaração a seguir, significa que o valor de cada elemento da matriz não pode ser alterado:

const char arr [] = 'a', 'b', 'c', 'd';

Seja um 'a', 'b', 'c' ou 'd', ainda não pode ser alterado para algum outro valor (personagem).

Uma situação semelhante é aplica -se a um objeto instanciado de uma classe. Considere o seguinte programa:

#incluir
usando namespace std;
CLA CLA

público:
char ch0 = 'a';
char ch1 = 'b';
char ch2 = 'c';
char ch3 = 'd';
;
int main ()

const cla obj;
retornar 0;

Devido à declaração "const cla obj;" com const na função main (), nem 'a' nem 'b' nem 'c' nem 'd' podem ser alterados para algum outro valor.

Especificadores da classe de armazenamento:

Os especificadores de classe de armazenamento são estáticos, mutáveis, thread_local e externo.

O Especificador de classe de armazenamento estático

O especificador de classe de armazenamento estático permite que a variável viva após o passar do escopo, mas não pode ser acessado diretamente.

O programa a seguir ilustra isso, com uma função recursiva:

#incluir
usando namespace std;
int funct ()

estático int stac = 10;
cout << stac < 50)

cout << '\n';
retornar 0;

funct ();

int main ()

funct ();
retornar 0;

A saída é:

10 20 30 40 50 50

Se uma variável estática não for inicializada em sua primeira declaração, assume o valor padrão do seu tipo.

O especificador estático também pode ser usado com membros de uma classe; O uso aqui é diferente. Aqui, ele permite que o membro seja acessado sem instanciação para o objeto.

O programa a seguir ilustra isso para um membro de dados:

#incluir
usando namespace std;
CLA CLA

público:
estático const int num = 8;
;
int main ()

cout << Cla::num << '\n';
retornar 0;

A saída é:

8

O membro estático de dados deve ser constante. Observe que o uso do operador de resolução do escopo para acessar a variável estática fora de seu escopo (na função principal).

O programa a seguir ilustra o uso de "estático" para uma função de membro:

#incluir
usando namespace std;
CLA CLA

público:
Método Void estático ()

cout << "Of static member function!" << '\n';

;
int main ()

Cla :: Method ();
retornar 0;

A saída é:

Da função estática do membro!

Observe que o uso do operador de resolução do escopo para acessar a função estática do membro fora de seu escopo (na função principal).

O especificador mutável

Lembre -se, de cima, que se um objeto instanciado começar com const, o valor de qualquer um de seus membros normais de dados não pode ser alterado. E para que qualquer membro desse dados seja alterado, ele deve ser declarado, mutável.

O programa a seguir ilustra o seguinte:

#incluir
usando namespace std;
CLA CLA

público:
char ch0 = 'a';
char ch1 = 'b';
char mutável ch2 = 'c';
char ch3 = 'd';
;
int main ()

const cla obj;
obj.ch2 = 'z';
cout << obj.ch0 << " << obj.ch1 << " << obj.ch2 << " << obj.ch3 << " << '\n';
retornar 0;

A saída é:

'a "b" z "d'

O especificador Thread_local

Na execução normal de um programa, um segmento de código é executado, depois o próximo segmento de código, seguido por outro segmento de código depois disso, e assim por diante. Esse é um tópico; o tópico principal. Se dois segmentos de código executarem ao mesmo tempo (mesma duração), é necessário um segundo tópico. O resultado do segundo fio pode até estar pronto antes do tópico principal.

A função principal () é como o tópico principal. Um programa pode ter mais de dois tópicos para um comportamento tão assíncrono.

O segundo fio precisa de um escopo (escopo do bloco) para operar. Isso geralmente é fornecido pelo escopo da função, uma função. Uma variável em um escopo externo que pode ser visto no escopo do segundo fio.

O programa curto a seguir ilustra o uso do especificador Thread_local:

#incluir
#incluir
usando namespace std;
thread_local int inter = 1;
void Thread_function ()

inter = inter + 1;
cout << inter << "nd thread\n";

int main ()

Thread Thr (& Thread_function); // THR começa a correr
cout << inter << "st or main thread\n";
Thr.juntar(); // O tópico principal aguarda o tópico, THR para terminar
retornar 0;

A saída é:

1º ou principal tópico
2º thread

A variável, inter, precedida por thread_local, significa que a inter possui uma instância separada em cada thread. E que pode ser modificado em threads diferentes para ter valores diferentes. Neste programa, ele é atribuído o valor, 1 no encadeamento principal e modificado para o valor, 2 no segundo tópico.

Um tópico precisa de um objeto especial para operar. Para este programa, a biblioteca incluída por "#include" tem uma classe chamada um tópico, do qual o objeto Thr foi instanciado. O construtor para este objeto exige uma referência à função do thread como um argumento. O nome da função Thread neste programa é thread_function ().

A função de junção () para o objeto especial, em sua posição empregada, faz com que o fio principal aguarde o segundo fio que termine de executar antes de continuar a executar; caso contrário, a função principal () pode sair sem o (segundo) encadeamento com thread ter tendo produziu seu resultado.

O especificador externo

Em termos simples, para uma declaração, a memória não é alocada para a variável ou função, enquanto para uma definição, a memória é alocada. A palavra reservada externa permite que uma variável ou função global seja declarada em um arquivo, mas definida em outro. Esses arquivos são chamados de unidades de tradução para o aplicativo C ++ completo.

Digite o seguinte programa e salve-o com o nome do arquivo, MainFile:

#incluir
usando namespace std;
int myint;
const char ch;
void myfn ();
int main ()

myfn ();
retornar 0;

A variável, myint, a variável constante, ch e a função, myfn (), foram declarados sem serem definidos.

Digite o seguinte programa com as definições e salve-o com o nome de arquivo, outro arquivo, no mesmo diretório:

#incluir
usando namespace std;
int myint = 10;
const char ch = 'c';
void myfn ()

cout << "myFn() says " << myInt << " and " << ch <<'\n';

Tente compilar o aplicativo no terminal (prompt de comando DOS) com o seguinte comando e observe que ele pode não compilar:

G ++ MainFile.CPP Outro arquivo.CPP -O completo.exe

Agora, precede as três declarações no arquivo principal com a palavra "externo", como segue:

extern int myint;
extern const char ch;
extern void myfn ();

Reave o arquivo principal. Compilar o aplicativo com:

G ++ MainFile.CPP Outro arquivo.CPP -O completo.exe

(É assim que os arquivos separados para o mesmo aplicativo são compilados em C ++)

E deve compilar. Agora, execute o aplicativo, completo.exe, e a saída deve ser:

myfn () diz 10 e c

Observe que, com o uso de "externo", uma variável constante pode ser declarada em um arquivo, mas definido em outro. Ao lidar com a declaração e definição da função em diferentes arquivos, o uso de externo é opcional.

Quando usar externo? Use -o quando não tiver arquivos de cabeçalho com declarações globais.

"Extern" também é usado com declarações de modelo - veja mais adiante.

Conclusão:

Uma variável precedida com const e/ou volátil é um tipo qualificado por CV. Uma variável, não precedida com const ou volátil ou ambos, é do tipo CV-Unqualified.

Os especificadores de classe de armazenamento são estáticos, mutáveis, thread_local e externo. Eles afetam a vida útil (duração), local e modo de emprego de variáveis ​​em uma aplicação.