Aprenda C++

  • Página Inicial
  • Contato!
  • Tudo sobre C++ Parte 1!
  • Tudo sobre C++ Parte 2!
  • Tudo sobre C++ Parte 3!
  • Tudo sobre C++ Parte 4!
  • Tudo sobre C++ Parte 5!
  • Tudo sobre C++ Parte 6!
  • Tudo sobre C++ Parte 7!
  • Tudo sobre C++ Parte 8!
  • Tudo sobre C++ Parte 9!
  • Tudo sobre C++ Parte 10!
  • Tudo sobre C++ Parte 11!
  • Tudo sobre C++ Parte 12!
  • Tudo sobre C++ Parte 13!
  • Tudo sobre C++ Parte 14!
  • Tudo sobre C++ Parte 15!
  • Tudo sobre C++ Parte 16!
  • Tudo sobre C++ Parte 14

    Inicialização Uniforme em C++11

    Primeiro, vamos no compilador do Codeblocks (em Settings e Compiler) e escolha a opção de especicação 11 (o padrão é 98). A versão 11 tem tudo das anteriores, então dá para compilar normalmente versões antigas. Caso não apareça a opção, clique na opção Do C++ ISO 1998 e vá em "Modify Flag", e altere "-std=c++98" para "-std=c++11"

    A inicialização uniforme é uma técnica que consiste em facilitar em padronizar as inicializações dentro do C++, seja de uma variável, struct, classe, etc.

    Veja o método antigo abaixo:

    
    int main() {
        int num = 10;
    
        return 0;
    }
    
    

    E no método moderno, faremos assim:

    
    int main() {
        int num{10};
    
        return 0;
    }
    
    

    Isso também é possível também em outros elementos, dessa forma:

    
    int main() {
        int num{10};
        string nome{"Texto"};
        vector<int> valores{1, 2, 3, 4, 5}; // Incluir vector
        map<string, string> capitais{{"MG", "Belo Horizonte"}}; // Incluir map
    
        return 0;
    }
    
    

    PS: O map recebe dois elementos, no caso acima, duas strings

    E também podemos inicializar structs assim, sempre na mesma ordem dos atributos:

    
    struct pessoa {
        string nome;
        int idade;
    };
    
    int main() {
        pessoa p1{"Bruno", 38}; // Sempre na ordem dos elementos do struct
        pessoa p2{"Nome", 100};
    
        return 0;
    }
    
    

    E com classes, nem precisamos criar construtores, podemos fazer da mesma forma do struct, nesse caso, e sem precisar indicar ponteiros, dessa forma:

    
    class Veiculo {
        public:
            int tipo;
            string nome;
    };
    
    int main() {
        Veiculo v1{1, "Fusca"}; // Sempre na ordem dos atributos da classe
        Veiculo v2{2, "Uno"};
    
        return 0;
    }
    
    

    Para exibir, fazemos assim:

    
    int main() {
        int num{10};
        string nome{"Texto"};
        vector<int> valores{1, 2, 3, 4, 5}; // Incluir vector
        map<string, string> capitais{{"MG", "Belo Horizonte"}}; // Incluir map
        pessoa p1{"Bruno", 38}; // Sempre na ordem dos elementos do struct
        pessoa p2{"Nome", 100};
        Veiculo v1{1, "Fusca"}; // Sempre na ordem dos atributos da classe
        Veiculo v2{2, "Uno"};
    
        cout << nome << endl;
    
        cout << endl;
    
        for(vector<int>::iterator it = valores.begin(); it != valores.end(); it++) { // Iterator
            cout << *it << endl;
        }
    
        cout << endl;
    
        for(map<string, string>::iterator it = capitais.begin(); it != capitais.end(); it++) { // Iterator
            cout << it->first << " - " << it->second << endl;
        }
    
        cout << endl;
    
        cout << p1.nome << " - " << p1.idade << endl;
        
        cout << endl;
    
        cout << v1.tipo << " - " << v1.nome << endl; // Classes em C++ modero usam ponto
        
        cout << endl;
    
        return 0;
    }
    
    

    Os vetores também podem ser inicializados de forma parecida com essa:

    
    int vetor[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    

    Classes de Armazenamento em C++11 - auto, register, static

    O auto, basicamente, é usado para declarar uma variável de qualquer tipo, mas isso não quer dizer que a variável se torna dinâmica, e sim que o tipo dela vai ser definido automaticamente na inicialização da mesma, por exemplo:

    
    auto num = 10; // Essa variável sempre será int.
    auto texto = "Palavra"; // Essa variável sempre será const char*.
    
    

    Por esse motivo acima, toda variável auto tem que ser inicializada, e não pode ser atribuída depois.

    Como também podemos colocar variáveis para receber valores retornados de funções, dessa forma:

    
    int soma(int n1, int n2) {
        return n1 + n2;
    }
    
    string canal() {
        return "Nome do Canal";
    }
    
    int main() {
        auto res = soma(10, 5);
        auto nome = canal();
    
        cout << res << endl;
        cout << nome << endl;
    
        return 0;
    }
    
    

    Também podemos colocar uma função do tipo auto, mas tem que indicar o tipo de retorno, dessa forma:

    
    auto soma(double n1, double n2)->int {
        return n1 + n2;
    }
    
    

    PS: O próprio método main pode ser escrito dessa forma em C++ moderno.

    Nesse caso acima, caso exista uma variável que receba esse retorno, ela deverá estar como auto também.

    Como sabemos, um vector faríamos a declaração e exibição assim:

    
    int main() {
        vector<int> v{10, 20, 30, 40, 50, 60, 70}; // Incluir vector
    
        for(vector<int>::iterator it = v.begin(); it != v.end(); it++) {
            cout << *it << endl;
        }
    
        return 0;
    }
    
    

    Mas o mesmo laço for pode ser feito dessa forma:

    
    for(auto it = v.begin(); it != v.end(); it++) {
        cout << *it << endl;
    }
    
    

    Isso acima pode ser feito com map, list e outros elementos.

    Quando declaramos uma variável com a palavra register, estamos pedindo para que o programa armazene a variável em um registrador no processador, e não na memória RAM (é um pedido ao sistema, se não for possível armazenar no registrador ele armazena na RAM mesmo, na maioria das vezes). Isso é usado em variáveis que precisamos acessar muito rapidamente, como um iterator ou qualquer elemento contador de um laço de repetição, por exemplo:

    
    for(register int cont = 0; cont <= 10; cont++) { 
        cout << cont << endl;
    }
    
    

    O static é um modificador de acesso.

    Veja um exemplo de uso de função normal:

    
    void somador() {
        int i = 0;
        i++;
        cout << i << endl;
    }
    
    int main() {
        somador();
        somador();
        somador();
        somador();
        somador();
        somador();
        somador();
    
        return 0;
    }
    
    

    No modo acima, em toda chamada de função ele criará uma nova declaração da variável local da mesma, que sempre voltará ao 0 e incrementará para 1.

    Agora veja a atribuição da variável com static

    
    void somador() {
        static int i = 0;
        i++;
        cout << i << endl;
    }
    
    int main() {
        somador();
        somador();
        somador();
        somador();
        somador();
        somador();
        somador();
    
        return 0;
    }
    
    

    Quando a variável é utilizada com static, ela sempre estará no mesmo endereço de memória, e como já estará criada, a mesma continuará a ser incrementada cada vez que a função for chamada, indo por 1, 2, 3, 4 e assim por diante. Não criará outra inicialização. O static também pode ser usado em funções, de forma que ele só pode ser usado no mesmo arquivo de código-fonte.

    Classes de Armazenamento Extern em C++11

    Primeiramente, crie um novo arquivo cpp com o nome auxiliar, no projeto.

    No main, declare uma variável assim:

    
    int num{10};
    
    int main() {
    
        return 0;
    }
    
    

    No auxiliar, coloque isso (não esqueça de incluir o iostream e colocar o namespace std):

    
    int num;
    
    void impNum() {
        cout << num << endl;
    }
    
    

    E no main, faça as alterações assim:

    
    void impNum();
    
    int num{10};
    
    int main() {
        impNum();
    
        return 0;
    }
    
    

    O código acima não compilará, por ter mais de uma declaração pra mesma variável, por isso no auxiliar devemos indicar que essa variável é externa, dessa forma:

    
    extern int num;
    
    void impNum() {
        cout << num << endl;
    }
    
    

    No caso acima, o num do extern não é uma declaração, e sim o acesso, a declaração é no main.

    PS: Evite inicializar variáveis com extern, inicialize ela no local onde ela está definida, no caso acima, no main.

    Dessa forma, não precisamos colocar um arquivo no cabeçalho do outro.

    Tente colocar uma variável assim no auxiliar:

    
    extern int num;
    
    int valor{50};
    
    void impNum() {
        cout << num << endl;
    }
    
    

    E no main, coloque assim:

    
    void impNum();
    
    int num{10};
    extern int valor;
    
    int main() {
        impNum();
        cout << valor << endl;
    
        return 0;
    }
    
    

    Ou seja, a variável pode ser declarada em qualquer arquivo e o extern pode ser usado em qualquer arquivo.

    Agora sim criaremos um arquivo de cabeçalho h (que deverá ser incluído) com o nome variaveis e coloque uma variável int com qualquer número, e no main, coloque esse código:

    
    int main() {
        impNum();
        cout << valor << endl;
        cout << numero << endl; // Isso vem da inclusão do arquivo h
    
        return 0;
    }
    
    

    PS: Podemos também fazer isso com os métodos, no caso, onde utilizarmos o extern, colocamos o método e os parâmetros como uma declaração.

    For com Base em Intervalo e For-range declaration em C++11

    Podemos simplificar o for nos casos de aplicações que podem ser iterados.

    Normalmente, usaríamos um laço for para ler um vetor assim:

    
    int main() {
        int x[10]{10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
    
        for(int i = 0; i < 10; i++) {
            cout << x[i] << endl;
        }
    
        return 0;
    }
    
    

    Ou mesmo assim:

    
    int main() {
        int x[10]{10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
    
        for(int i = 0; i < sizeof(x) / sizeof(int); i++) {
            cout << x[i] << endl;
        }
    
        return 0;
    }
    
    

    Mas elementos que podem ser iterados (coleções, como vetores e vector e list), podem ser declarados assim:

    
    int main() {
        int x[10]{10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
    
        for(int i: x) {
            cout << i << endl; // Só coloca a variável do for
        }
    
        return 0;
    }
    
    

    PS: No caso acima, que é chamado de for range declaration ou for it, ele deverá ter a variável do mesmo tipo da coleção a ser exibida.

    Ou utilize auto também, dessa forma:

    
    int main() {
        vector<int> n{10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; // Importe vector
    
        for(auto i: n) {
            cout << i << endl;
        }
    
        return 0;
    }