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 15

    Funções Lambda em C++11

    As funções Lambda são funções anônimas, que não tem nome e pode ser anexada à uma variável ou outra função, e podem ser declaradas em qualquer parte do código e a partir desse ponto, pode ser usada quantas vezes for necessárias, e podemos passar uma lista de variáveis externas que queremos trabalhar dentro da nossa função. E elas também não precisam ser prototipadas (declaradas) inicialmente no código, antes do main.

    As funções Lambda tem essa estrutura: [capturaDeVariaveis](parâmetros)->tipoDeRetorno {corpoDaFuncao};.

    Basicamente, criamos uma declaração Lambda assim:

    
    int main() {
        [](){}; // Isso já é uma função Lambda, definida pelos colchetes.
    
        return 0;
    }
    
    

    Para exibir algo, atribuímos a Lambda à uma variável assim, e usamos como um método, assim:

    
    int main() {
        auto mensagem = [](){cout << "Introdução às Lambdas em C++!" << endl;};
    
        mensagem();
    
        return 0;
    }
    
    

    Veja um exemplo de uso de função com parâmetros e retorno:

    
    int main() {
        auto maior = [](int n1, int n2)->int{return (n1 > n2) ? n1 : n2;};
    
        cout << maior(2, 6) << endl;
    
        return 0;
    }
    
    

    A função Lambda não tem nome, mas como está associada à uma variável, ela pode ser invocada como uma função.

    Podemos usar um vector para podemos passar quantidades diferentes de parâmetros, por exemplo:

    
    int main() {
        auto maior = [](vector<int> n)->int { // Importe vector
            auto m = 0;
    
            for(int x: n) {
                m = (m > x) ? m : x;
            }
    
            return m;
        };
    
        cout << maior({9, 8, 2, 10, 45, 20, 5, 34, 12}) << endl;
    
        return 0;
    }
    
    

    No caso acima, com o uso de vector, podemos inserir a quantidade de números que quisermos de forma dinâmica.

    A captura de variáveis pode ser feita de tal forma:

    
    int main() {
        int x1, x2, x3, x4;
        x1 = 10;
        x2 = 5;
        x3 = 2;
        x4 = 12;
    
        auto soma = [x1, x2, x3, x4]()->int{return x1 + x2 + x3 + x4;};
    
        cout << soma() << endl;
    
        return 0;
    }
    
    

    Ou colocando o símbolo de = na captura de variáveis, que somará todas as variáveis do escopo, assim:

    
    int main() {
        int x1, x2, x3, x4;
        x1 = 10;
        x2 = 5;
        x3 = 2;
        x4 = 12;
    
        auto soma = [=]()->int{return x1 + x2 + x3 + x4;};
    
        cout << soma() << endl;
    
        return 0;
    }
    
    

    Pode ser utilizado o igual no Lambda com argumentos também, dessa forma:

    
    int main() {
        int x1, x2, x3, x4;
        x1 = 10;
        x2 = 5;
        x3 = 2;
        x4 = 12;
    
        auto maior = [=](vector<int> n)->int { // Importe vector
            auto m = 0;
    
            for(int x: n) {
                m = (m > x) ? m : x;
            }
    
            return m;
        };
    
        cout << maior({1, 2, 3, 4, 5, 6, 7, 8, 9}) << endl;
    
        return 0;
    }
    
    

    Podemos fazer a soma assim:

    
    int main() {
        auto soma = [](vector<int> n)->int { // Importe vector
            auto s = 0;
    
            for(int x: n) {
                s += x;
            }
    
            return s;
        };
    
        cout << soma({1, 2, 3, 4, 5, 6, 7, 8, 9}) << endl;
    
        return 0;
    }
    
    

    Constantes em C++11

    Seguindo a mesma lógica do C, só poderíamos definir constantes definindo uma macro no cabeçalho, por exemplo:

    
    #include <iostream>
    #define PI 3.141592
    
    using namespace std;
    
    int main() {
        cout << PI << endl;
    
        return 0;
    }
    
    

    Mas no C++ podemos ter constantes, usando a palavra const antes do atributo e inicializando ela:

    
    #include <iostream>
    
    using namespace std;
    
    int main() {
        const double PI = 3.141592;
    
        cout << PI << endl;
    
        return 0;
    }
    
    

    PS: O const pode ser usado também em funções e métodos, desde que estes não façam alterações em variáveis ou atributos.

    Pair - Dados em Pares

    O pair se diferencia dos outros tipos de contâineres, por permitir sempre armazenar um par de dados, tipo um int e um string, ou um bool e um int, uma classe e um char, e etc.

    Inicialmente, inclua a biblioteca utility, e coloque esse código:

    
    pair<int, string> par(10, "Teste"); // Inclua utility
    
    cout << par.first << " - " << par.second << endl;
    
    

    Como vimos acima, o objeto pair foi definido como o primeiro sendo int e o segundo string, dessa forma, podemos exibir os elementos usando os atributos first e second, respectivamente.

    Podemos também fazer sem inicializar o pair, assim:

    
    pair<int, string> par;
        
    par.first = 100;
    par.second = "Cursos";
    
    cout << par.first << " - " << par.second << endl;
    
    

    Para declarar vetores de pair, fazemos assim:

    
    const int TAM = 3;
    
    pair<int, string> pares[TAM];
    
    pares[0].first = 100;
    pares[0].second = "Cursos";
    
    pares[1].first = 200;
    pares[1].second = "C++";
    
    pares[2].first = 300;
    pares[2].second = "Pair";
    
    

    Podemos usar também o make_pair para facilitar a criação de pares:

    
    const int TAM = 3;
    
    pair<int, string> pares[TAM];
    
    pares[0] = make_pair(100, "Cursos");
    
    pares[1] = make_pair(200, "C++");
    
    pares[2] = make_pair(300, "Pair");
    
    for(int i = 0; i < 3; i++) {
        cout << pares[i].first << " - " << pares[i].second << endl;
    }
    
    

    PS: Podemos passar um pair dentro de outro pair, por exemplo:

    
    pair<int, pair<string, double>> produtos[3];
    
    produtos[0] = make_pair(10, make_pair("Mouse", 10.55));
    produtos[1] = make_pair(20, make_pair("Teclado", 50.49));
    produtos[2] = make_pair(30, make_pair("Monitor", 399.98));
    
    for(int i = 0; i < 3; i++) {
        cout << produtos[i].first << " - " << produtos[i].second.first << " - " << produtos[i].second.second << endl;
    }
    
    

    Pode ver que da forma acima, o pair externo tem seu first e seu second, e nesse second tem outro pair, quando chamamos atributos deles, usamos o second.first e o second.second, se o pair interno for o primeiro, é first.first e first.second. Esteja atento quanto à isso.

    Claro que em C++ é mais interessante usar o vector, dessa forma:

    
    vector<pair<int, string>> prod; // Importe vector
    
    prod.push_back(make_pair(10, "Mouse"));
    prod.push_back(make_pair(20, "Teclado"));
    prod.push_back(make_pair(30, "Monitor"));
    
    for(int i = 0; i < prod.size(); i++) {
        cout << prod[i].first << " - " << prod[i].second << endl;
    }
    
    

    PS: Podemos usar o for it também:

    
    for(auto i: prod) {
        cout << i.first << " - " << i.second << endl;
    }
    
    

    Map - Container de Associação Chave x Valor

    O Map é um containers de associação de chave e valor, ele parece um pouco com o pair, mas ele associa o segundo elemento (valor) ao primeiro (chave).

    Primeiro, inclua a biblioteca map, e coloque esse código:

    
    map<int, string> prod; // Inclua map
    
    

    No código acima, a chave é do tipo int, e o valor é string, o valor é associado à chave, mas eles podem ser de tipos diferentes, pode também receber structs, classes e etc., e podem ser usado com vector, como acontece com os pairs.

    Para adicionar elementos, faça como se faz com um vetor:

    
    map<int, string> prod; // Inclua map
        
    prod[0] = "Mouse";
    prod[1] = "Teclado";
    prod[2] = "Monitor";
    prod[3] = "Caixa";
    
    for(int i = 0; i < 4; i++) {
        cout << prod[i] << endl;
    }
    
    

    O que está dentro dos colchetes é a chave (no caso, int, poderia ser outro tipo, definido no map), e o valor associado a ela é o que está após o símbolo de atribuição.

    Podemos exibir também dessa forma:

    
    map<int, string> prod; // Inclua map
    
    prod[0] = "Mouse";
    prod[1] = "Teclado";
    prod[2] = "Monitor";
    prod[3] = "Caixa";
    
    for(auto it = prod.begin(); it != prod.end(); it++) {
        cout << it->first << " - " << it->second << endl;
    }
    
    

    Da forma acima, usando o first, imprime a chave, e o second imprime o valor, independente do tipo de ambos.

    Pra simplificar, podemos usar o for it assim:

    
    for(auto it: prod) {
        cout << it.first << " - " << it.second << endl;
    }
    
    

    Mas o certo é usar o insert, onde inserimos os pares decladados no map (na mesma ordem dos tipos pré-definidos, utilizando o pair:

    
    map<int, string> prod; // Inclua map
    
    prod.insert(pair<int, string>(0, "Mouse")); // Inclua utility
    prod.insert(pair<int, string>(1, "Teclado"));
    prod.insert(pair<int, string>(2, "Monitor"));
    prod.insert(pair<int, string>(3, "Caixa"));
    
    for(auto it: prod) {
        cout << it.first << " - " << it.second << endl;
    }
    
    

    Para apagar um índice, utilize o erase com o conteúdo da chave a ser apagada:

    
    prod.erase(2);
    
    

    PS: Lembrando que isso não é a posição do elemento, ele vai procurar o elemento com a chave 2, se eles forem enumerados com 10, 20, 30 e 40, ou for outro tipo na chave, como o char, ele não apagará a "posição 2" do map.

    Para apagar todos os elementos do map, use o clear, assim:

    
    prod.clear();
    
    

    Temos também o find, que procura uma chave do map, e retorna o valor correspondente à esta:

    
    map<int, string> prod; // Inclua map
    map<int, string>::iterator itmap;
    
    prod.insert(pair<int, string>(10, "Mouse")); // Inclua utility
    prod.insert(pair<int, string>(20, "Teclado"));
    prod.insert(pair<int, string>(30, "Monitor"));
    prod.insert(pair<int, string>(40, "Caixa"));
    prod.insert(pair<int, string>(50, "Microfone"));
    prod.insert(pair<int, string>(60, "Gabinete"));
    prod.insert(pair<int, string>(70, "Câmera"));
    
    itmap = prod.find(30);
    
    if(itmap == prod.end()) {
        cout << "Produto não Encontrado!" << endl;
    }
    else {
        cout << "Produto em Estoque: " << endl;
        cout << "Código: " << itmap->first << endl;
        cout << "Produto: " << itmap->second << endl;
        cout << "----------------------------------" << endl;
    }
    
    

    Agora tente passar uma chave que não existe nesse mesmo find.

    Podemos também excluir uma quantidade específica de produtos, usando o erase, dessa forma:

    
    prod.erase(prod.begin(), prod.find(30));
    
    

    PS: Ele não excluí o conteúdo da chave passada, e sim até antes dele.

    Da forma acima, ele excluí da primeira posição até antes da especificada, mas podemos escolher uma faixa específica assim:

    
    prod.erase(prod.find(30), prod.find(60));