C ++

Qualificadores C ++ e especificadores de classe de armazenamento

Qualificadores 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 é um tipo cv não qualificado. Por outro lado, a declaração de um objeto que é precedido por const e / ou volatile é um tipo cv qualificado. Se um objeto for declarado const, o valor em sua localização não pode 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 referem-se à vida, lugar e maneira em que um tipo existe. Os especificadores da classe de armazenamento são static, mutable, thread_local e extern.

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:

const

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

int const theInt = 5;

O valor de 5 no armazenamento para o Int 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 deveria ser constante. Valores de objeto que têm a ver com portas IO mapeadas em memória ou rotinas de serviço de interrupção de dispositivos periféricos podem sofrer interferência do compilador. Para evitar tal interferência, torne a variável volátil, como:

int volatile portVal;
portVal = 26904873;
ou como:
int volátil portVal = 26904873;

Combinando const e volatile:

const e volatile podem ocorrer em uma instrução da seguinte forma:

int const volatile portVal = 26904873;

qualificadores cv

Uma variável precedida de const e / ou volatile é um tipo cv qualificado. Uma variável não precedida de const ou volatile ou ambos é do tipo cv-unqualified.

Encomenda:

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

Ainda não foi concluído se const e volatile são da mesma categoria.

Matriz e objeto instanciado:

Quando uma matriz é declarada constante, como na instruçã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 (caractere).

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

#incluir
usando namespace std;
classe Cla

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

const Cla obj;
return 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 de classe de armazenamento:

Os especificadores da classe de armazenamento são static, mutable, thread_local e extern.

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 seu escopo ter passado, mas não pode ser acessada 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';
return 0;

funct ();

int main ()

funct ();
return 0;

O resultado é:

10 20 30 40 50

Se uma variável estática não for inicializada em sua primeira declaração, ela assume o valor padrão para 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;
classe Cla

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

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

O resultado é:

8

O membro de dados estáticos deve ser constante. Observe que o uso do operador de resolução de 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;
classe Cla

público:
método void estático ()

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

;
int main ()

Cla :: method ();
return 0;

O resultado é:

Da função de membro estático!

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

O especificador mutável

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

O programa a seguir ilustra isso:

#incluir
usando namespace std;
classe Cla

público:
char ch0 = 'a';
char ch1 = 'b';
caractere 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';
return 0;

O resultado é:

'a "b" z "d'

O especificador thread_local

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

A função main () é como o thread principal. Um programa pode ter mais de dois threads para tal comportamento assíncrono.

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

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.Junte(); // thread principal espera pelo thread, thr para terminar
return 0;

O resultado é:

1ª linha de discussão ou principal
2ª discussão

A variável, inter, precedida por thread_local, significa que inter tem uma instância separada em cada thread. E que pode ser modificado em diferentes threads para ter diferentes valores. Neste programa, é atribuído o valor 1 na thread principal e modificado para o valor 2 na segunda thread.

Um thread precisa de um objeto especial para operar. Para este programa, a biblioteca incluída por “#include ”Tem uma classe chamada thread, a partir da qual o objeto thr foi instanciado. O construtor para este objeto leva uma referência à função thread como um argumento. O nome da função thread neste programa é thread_function ().

A função de membro join () para o objeto especial, em sua posição empregada, faz o thread principal esperar que o segundo thread termine de executar antes de continuar a executar, caso contrário, a função main () pode sair sem que o (segundo) thread tenha 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 externa reservada permite que uma variável global ou função 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 ();
return 0;

A variável, myInt, a variável constante, ch, e a função, myFn (), foram declaradas sem serem definidas.

Digite o seguinte programa com as definições e salve-o com o nome do arquivo, otherFile, 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 do DOS) com o seguinte comando e observe que pode não ser compilado:

g ++ mainfile.cpp otherFile.cpp -o completo.Exe

Agora, preceda as três declarações em mainFile com a palavra "extern", como segue:

extern int myInt;
extern const char ch;
extern void myFn ();

Salve novamente mainFile. Compile o aplicativo com:

g ++ mainfile.cpp otherFile.cpp -o complete.Exe

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

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

myFn () diz 10 e c

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

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

“Extern” também é usado com declarações de modelo - veja mais tarde.

Conclusão:

Uma variável precedida de const e / ou volatile é um tipo cv qualificado. Uma variável, não precedida de const ou volatile ou ambos, é um tipo cv-não qualificado.

Os especificadores da classe de armazenamento são static, mutable, thread_local e extern. Eles afetam o tempo de vida (duração), o local e a forma de emprego das variáveis ​​em um aplicativo.

Jogos HD Remasterizados para Linux que nunca tiveram uma versão Linux anterior
Muitos desenvolvedores e editores de jogos estão apresentando remasterização em HD de jogos antigos para estender a vida da franquia, por favor, os fã...
Como usar o AutoKey para automatizar jogos Linux
AutoKey é um utilitário de automação de desktop para Linux e X11, programado em Python 3, GTK e Qt. Usando sua funcionalidade de script e MACRO, você ...
Como mostrar o contador de FPS em jogos Linux
Os jogos Linux tiveram um grande impulso quando a Valve anunciou o suporte Linux para o cliente Steam e seus jogos em 2012. Desde então, muitos jogos ...