Clique sobre os tópicos listados abaixo para navegar até o conteúdo desejado.

C++ possui os Smart Pointers que são classes que facilitam o uso de ponteiros fornecendo gerenciamento de memória. Esses tipos de ponteiros são recomendados para evitar erros de memória.

De forma resumida, um ponteiro é um tipo de dados que armazena endereço de memória que apontam uma variável, função, vetor, matriz, estrutura de dado ou outros.

Com os ponteiros suportam a aplicação de algumas operações aritméticas, expressões de comparação e outros, para acessar nossas váriaveis de forma indireta.

O assunto ponteiro pode ser visto também em Tutorial C: Ponteiro.

A declaração de uma variável ponteiro é semelhante a outros tipos de dados execeto pelo uso do operador (*), como pode ser conferido abaixo:

Sintaxe
tipo_dado *nome_ponteiro; //não iniciado

tipo_dado* nome_ponteiro = nullptr; //não iniciado

Nos exemplos abaixo, vamos utilizar os tipos de dados Enum, Struct e Union que podem ser vistos em C++ Básico: Enum, C++ Básico: Struct e C++ Básico: Union.

Exemplo 1
#include <iostream>
using namespace std;

enum enum_exemplo{
    VALOR1 = 1,
    VALOR2 = 2
};

struct exemplo{
    int id;
    string desc;
};

union uniao{
    int id;
    float valor;
};

int main()
{
    //ponteiros
    int *pi;
    float *pf;
    char *pc;
    struct exemplo* pse;
    enum_exemplo* pe;
    uniao* pu;
}
Saída
-

A atribuição de uma valor uma ponteiro é feito utilizando o operador (&) que significa o endereço de uma variável, vetor, struct ou outro.

Sintaxe
tipo_dado *nome_ponteiro = &var1; //iniciado
Exemplo 2
#include <iostream>
using namespace std;

enum enum_exemplo{
    VALOR1 = 1,
    VALOR2 = 2
};

struct exemplo{
    int id;
    string desc;
};

union uniao{
    int id;
    float valor;
};

int main()
{
    int i =10, *pi;
    pi = &i;//atribuição
    
    float f= 7.77, *pf;
    pf = &f;//atribuição
    
    char c = 'A', *pc;
    pc = &c;//atribuição
    
    struct exemplo st = {1,"Teste"}, *pse;
    pse = &st; //atribuição
    
    enum_exemplo e = VALOR1, *pe;
    pe = &e;//atribuição
    
    uniao u, *pu; 
    pu = &u;//atribuição
}
Saída
-

Com o uso de um ponteiro, podemos acessar indiretamente o conteúdo de variáveis com o próprio ponteiro ao utilizá-lo, prefixado, com o operador (*), como pode ser visto no exemplo abaixo.

Sintaxe
*variavel_ponteiro
Exemplo 3
#include <iostream>
using namespace std;

int main()
{
    int var1 = 10;
    int *ref = &var1; 
    
    cout << *ref; //acesso indireto à variável
}
            
Saída
10

O acesso a tipos de dados que possuem membros como union e struct pode ser feito utilizando as sintaxes mostradas abaixo:

Sintaxe
variavel_ponteiro->nome_membro;
(*variavel_ponteiro).nome_membro;
Exemplo 4
#include <iostream>
using namespace std;

enum enum_exemplo{
    VALOR1 = 1,
    VALOR2 = 2
};

struct exemplo{
    int id;
    string desc;
};

union uniao{
    int id;
    float valor;
};

int main()
{ 
    int i =10,*pi;
    pi = &i;//atribuição
    cout << *pi << endl; //acesso indireto

    float f= 7.77, *pf;
    pf = &f;//atribuição
    cout << *pf << endl; //acesso indireto

    char c = 'A', *pc;
    pc = &c;//atribuição
    cout << *pc << endl; //acesso indireto

    struct exemplo st = {1,"Teste"}, *pse;
    pse = &st; //atribuição
    cout << pse->id << endl; //acesso indireto

    enum_exemplo e = VALOR1, *pe;
    pe = &e;//atribuição
    cout << *pe << endl; //acesso indireto

    uniao u, *pu; 
    pu = &u;
    u.id = 999;  
    cout << (*pu).id << endl; //acesso indireto
}
Saída
10
7.77
A
1
1
999

O tipo de dado ponteiro, permite que façamos uso de operadores aritméticos para que seja possível percorrer endereços de memória de forma justaposta ou indexada, diferente do tipo de dado reference.

Exemplo
variavel_ponteiro = variavel_ponteiro + 1;
variavel_ponteiro++;

É importante observar que como estamos lidando com endereços de memória, o programador é responsável pelo uso correto da aritmética de ponteiros de acordo com o tamanho do tipo de dado.

Os operadores relacionais e alguns operadores aritméticos podem ser utilizados com ponteiros. Esses operadores podem ser conferidos na tabela abaixo:

Tab. 1: Operadores
Operador Descrição Exemplo
= Atribuição p1 = p2
>= Maior igual p1 >= p2
<= Menor igual p1 <= p2
!= Diferente p1 != p2
> Maior p1 > p2
< Menor p1 < p2
++ Incremento p++
-- Decremento p--
+ Soma p
- Substração p - 1
* Ponteiro *p
Exemplo 5
#include <iostream>
using namespace std;

int main()
{
    //4 bytes por elemento
    int v[3] = {1,2,3}; 
    
    int *pv = &v[0]; //ponteiro para primeiro elemento
    
    pv++; 
    cout << *pv << endl; //conteúdo da posição 1
    
    int *p0 = &v[0];
    int *p1 = &v[1];
    int *p2 = &v[2];
    
    cout << boolalpha << (p0 == p1) << std::endl;
    cout << boolalpha << (p0 != p1) << std::endl;
    
    cout << boolalpha << (p0 < p1) << std::endl;
    cout << boolalpha << (p0 > p1) << std::endl;

    return 0;
}
Saída

2
false
true
true
false

O uso de ponteiros como parâmetros para funções é feita da mesma forma usada como com os tipos básicos de dados. A passagem de argumentos, por referência, é feita utilizando o operador (&) e o acesso indireto é feita utilizando o operador "*":

Exemplo 6
#include <iostream>
using namespace std;

void funcao( int *i, float *f, char *ch){
    cout << *i << endl;
    cout << *f << endl;
    *ch = *ch + 1; //alterando valor de ch indiretamente
    cout << *ch << endl;
}

int main()
{
    int a = -1;
    float f = 1.99;
    char ch = 'A';
    funcao(&a,&f,&ch);
    return 0;
}
Saída
-1
1.99
B

O retorno do tipo de dados ponteiros em funções é feita da mesma forma como qualquer outro tipo de dado. O tipo de dado ponteiro deve ser declarado no tipo de retorno de uma função e uma variável ponteiro deve ser retornada com o comando return.

Sintaxe
tipo_dado_retorno* nome_funcao(<lista_parametros>)
{
    //corpo omitido
	return variavel_ponteiro;
}
Exemplo 7
#include <iostream>
using namespace std;

int* funcao()
{
    int a = 999;
    int *p = &a;
    return p;
}

int main()
{
    
    int *v = funcao();
    cout << *v << endl;
    return 0;
}
Saída
999

A criação de vetores de ponteiros é feita da mesma forma utilizada para os tipos básicos de dados. Declaramos um vetor de acordo com o tipo de dado ponteiro desejado, utilizando o operador (*) e iniciamos seu conteúdo em que cada elemento ponteiro.

Exemplo 8
#include <iostream>
using namespace std;

int main()
{
    int *v[3]; //vetor de ponteiros
    
    //elementos do vetor
    int a = 1;
    int b = 2;
    int c = 3;
    
    //acesso e atribuição
    v[0] = &a;
    v[1] = &b;
    v[2] = &c;
    
    int *pnt; //ponteiro para percorrer vetor
    int *fim = v[0] + 3; //ponteiro para fim do vetor
    int *valor;
    
    for(pnt = v[0]; pnt != fim ; pnt++){
         cout << *pnt << endl;
    }
}
Saída
1
2
3

O acesso e alteração de elementos de um vetor de ponteiros é feita da mesma forma como em qualquer outro tipo de dado como mostrado no exemplo acima. A diferença é que lidamos com endereço de memória e não valores.

Com uso de ponteiro para função podemos atribuir uma função ao uma variáveil e invocá-la ou passar com função como argumento(callback). Para a criação de ponteiro para função use-se a sintaxe abaixo:

Sintaxe A
tipo_dado_retorno (*nome_funcao)(<lista_parametros>);
Sintaxe B
(*nome_variavel)(arg1, arg2, argN);

As sintaxes A e B acima, mostram respectivamente o declaração de um ponteiro para função e seu uso.

Exemplo 9
#include <iostream>
using namespace std;

void funcao(int i){
    cout << "chamada por ponteiro" << endl;
    cout << "valor:" << i << endl;
}

int main()
{
    void (*pfuncao)(int); //ponteiro p/ função
    pfuncao = &funcao; //atribuição de função ao ponteiro
    (*pfuncao)(777); //chamada a função
}
Saída
chamada via ponteiro
valor:777

Da mesma forma que podemos utilizar outros tipos de dados para criação de vetores, podemos criar vetores contendo ponteiros para função.

Sintaxe A
tipo_retorno (*nome_vetor[tamanho])(tipo_dado_param1, tipo_dado_paramN);
Sintaxe B
(*nome_vetor[indice])(arg1, arg2, argN)

As sintaxes A e B acima, mostram respectivamente o declaração de vetor de ponteiro para função e a chamada das funções via ponteiro.

Exemplo 10
#include <iostream>
using namespace std;

void funcao1(){
    cout << "funcao1" << endl;
}

void funcao2(){
    cout << "funcao2" << endl;
}

void funcao3(){
    cout << "funcao3" << endl;
}
int main()
{

    void (*vet_pnt_funcao[2])();
    
    vet_pnt_funcao[0] = &funcao1;
    vet_pnt_funcao[1] = &funcao2;
    vet_pnt_funcao[2] = &funcao3;
    
    (*vet_pnt_funcao[0])(); 
    (*vet_pnt_funcao[1])();
    (*vet_pnt_funcao[2])();
}
Saída
funcao1
funcao2
funcao3

Com o que foi mostrado no exemplo visto acima, podemos utlizar vetor de ponteiros para função como forma de substituição do comando switch.

  1. 29/07/2025 - revisão 4 - Correções: Objetivos; links e títulos, descriçao de seções, 'Ponteiro p/ função'; ajustes em sintaxes
  2. 30/09/2024 - revisão 3 - Correção: em 'intro', 'objetivos' e 'numeração de exemplos; ajustes gramaticais pontuais e outros
  3. 30/08/2024 - revisão 2 - Correção em links de objetivos
  4. 09/02/2024 - revisão 1 - Correção em navegação,css e erros gramaticais
  5. 30/06/2023 - versão inicial