O que exatamente faz "estático", quer dizer ao declarar "global" de variáveis em C++?
-
26-09-2019 - |
Pergunta
Esta é uma expansão do âmbito de um a pergunta anterior de minas.
O que exatamente é "estática", como é usado, e qual é o propósito de usar "estático" ao lidar com C++?
Obrigado.
Solução
A palavra-chave static
tem significados diferentes em C++, dependendo do contexto.
Quando declarar uma função livre ou uma variável global significa que a função não está disponível fora de uma única unidade de tradução:
// test.cpp
static int a = 1;
static void foo() {}
Se o resultado da compilação que a unidade de tradução que está ligado com uma tradução diferente da unidade que contém símbolos a
e foo
ele não vai quebrar a Regra de Definição, como neste particular, a unidade de tradução a
e foo
são privada símbolos.Este uso foi tornado obsoleto pela unnamed espaços de nomes.
// test2.cpp
namespace {
static int a = 1;
static void foo() {}
}
Quando declarar uma variável local dentro de uma função significa que a vida útil da variável estendem-se desde a primeira chamada para a função para a final do programa, e não apenas para a duração da chamada:
int foo() {
static int counter = 0;
return ++counter;
}
int main() {
for ( int i = 0; i < 10; ++i ) {
std::cout << foo() << std::endl;
}
}
No código anterior, counter
é inicializada uma vez quando foo
é chamado pela primeira vez, mas a variável que irá sobreviver a função e manter o valor em diferentes chamadas de função.O anterior código irá imprimir "1 2 3 4...10".Se a variável não foi declarada static
em seguida, a saída seria "1 1 1...1".
Dentro de um escopo de classe, static
significa que o membro é um membro da classe, e não de uma instância específica.Este uso é equivalente a usar na sua outra pergunta:o uso de determinado membro não está vinculado a qualquer objeto específico.
struct test {
int x;
static int y;
};
int test::y; // need to define it in one translation unit
int main() {
// test::x = 5; // !error cannot access a non-static member variable
// without an instance
test::y = 5; // ok
test t, other;
t.x = 10; // ok
t.y = 15; // ok, the standard allows calling a static member through
// an instance, but this is the same as test::y
}
Neste caso, o membro x
é um membro não estático atributo, e, como tal, é diferente x
para cada instância da classe.O programa de exemplo t.x
e other.x
referem-se a diferentes números inteiros.Por outro lado, y
é static
e, assim, não há uma única instância de test::y
o programa.Mesmo se o padrão permite chamar t.y
e other.y
as utilizações referem-se à mesma variável.O mesmo acontece com os métodos.Se eles são estáticos, eles são de classe em nível de métodos e pode ser chamado sem um exemplo, enquanto se eles não são estáticos, eles são aplicados a um exemplo concreto e o a.b
ou a->b
sintaxe deve ser usada.
Este uso de static
é semelhante ao uso da mesma palavra-chave em Java, enquanto que os outros dois não estão presentes nesse idioma.Há uma utilização da palavra-chave em Java que não está presente em C++, e que é a utilização da classe estática inicializadores (de um bloco de código no nível de classe, rodeado por static { ... }
).Em Java o bloco de código será executado quando a classe é carregada e apenas uma vez.A inicialização de variáveis de membro estático em C++ deve ser feito no inicializador da definição de variável.
Outras dicas
Isso significa que a variável é local para uma unidade de tradução (basta colocar, em um único arquivo de origem) e não pode ser acessado de fora dela. Esse uso da estática é de fato descontinuado no padrão C ++ atual - em vez disso, você deve usar namespaces anônimos:
static int x = 0;
deveria estar:
namespace {
int x = 0;
}
Este material parece ser muito bem coberto aqui.
Mas a paráfrase, há 2 usa em C
- Evitar o uso de uma variável global fora do escopo do arquivo que a define.
Permitir que variáveis locais dentro de uma função para persistem através de invocações da função, como no
int getNextId() { static int id = 0;identificação retorno++;}
C++ herda de ambos, e adiciona dois usos do seu próprio.
- variáveis de membro estático:Variáveis que são "compartilhados" através de todas as instâncias de uma classe, e também pode ser de acessos sem referência a uma instância da classe.Compartilhado parece ser a palavra errada, mas, em essência, eu acredito que o resultado é que qualquer referência a uma variável de membro estático referências o mesmo local da memória.
- métodos estáticos:Métodos que podem ser chamados sem referência a uma instância específica da classe que a define.
A estática basicamente significa que uma variável está ligada à vida útil do programa e não de qualquer função ou instância da classe. Quando você deve usá -lo? Não. Qual é o propósito? Dados de depuração, principalmente.
Geralmente, em C ++, se você se encontrar usando dados estáticos, você fez errado. Há momentos em que é apropriado, mas eles são muito raros.
Quando a estática é usada em uma classe em C ++, significa mais ou menos a mesma coisa que faz em Java. Para variáveis, significa que existe uma instância da variável para todas as classes e funções, significa que a função não acessa implicitamente o ponteiro.
Em C e C ++ quando estático é usado para uma variável ou função global, significa que a variável só pode ser referenciada no arquivo C ou C ++ atual. Em outras palavras, o compilador não deve gerar símbolos de realocação para a variável ou função.
Quando a estática é usada ao lado de uma variável em uma função local, isso significa que a variável não sai do escopo, mas manterá seu valor de chamada de função à chamada de função. A variável se torna efetivamente uma variável global que só pode ser acessada a partir da função especificada.
Os membros da classe estática são dados e funções associados à própria classe, e não aos objetos da classe.
No exemplo a seguir, a classe Fred possui um membro estático de dados x_ e um membro de dados da instância y_. Existe apenas uma cópia de Fred :: x_, independentemente de quantos objetos Fred são criados (incluindo nenhum objeto Fred), mas há um objeto Y_ por Fred. Assim, diz -se que X_ está associado à classe e Y_ está associado a um objeto individual da classe. Da mesma forma, a classe Fred possui uma função de membro estático f () e uma função de membro da instância G ().
class Fred {
public:
static void f() throw(); <-- 1
void g() throw(); <-- 2
protected:
static int x_; <-- 3
int y_; <-- 4
};
(1) Função de membro associada à classe
(2) Função do membro associada a um objeto individual da classe
(3) membro de dados associado à classe
(4) membro de dados associado a um objeto individual da classe
Uso:
Quando você deseja manter o trato do número de instâncias de uma classe criada, você usa a variável estática. Por exemplo, em uma classe de 'carro', cada instância do carro pode ter um número de série único (_Y neste caso) e a empresa pode querer acompanhar o número de carros produzidos (_x neste caso).