Quais são os casos de uso e as vantagens dos ponteiros? [fechadas]

10

Costumo lutar para ver as vantagens dos ponteiros (exceto para programação de baixo nível).

Por que usar char * em vez de uma String ou char [] ou quais vantagens a aritmética do ponteiro traz.

Então, quais são os profissionais e os casos de uso de ponteiros?

OliverS
fonte
6
Isso vai parecer um pouco elitista, mas IMHO, se você precisar perguntar sobre prós e contras dos indicadores, provavelmente não precisará deles.
Jas
3
Provavelmente! Mas a questão ainda é válida!
Zolomon
11
Isso também não é realmente independente de linguagem, pois nem todas as linguagens de programação têm indicadores reais no sentido C.
David Thornley

Respostas:

6

Ponteiros são necessários para localização dinâmica da memória, muitas estruturas de dados e manipulação eficiente de grandes quantidades de dados. Sem ponteiros, você teria que alocar todos os dados do programa globalmente ou em funções ou equivalentes e não teria nenhum recurso se a quantidade de dados crescesse além do que você originalmente havia permitido. Hesito em usar absolutos aqui, mas, tanto quanto sei, todas as linguagens modernas de computador têm indicadores de uma forma ou de outra.

Na maioria dos idiomas que usam ponteiros, existem certos tipos de referências que são ponteiros, e talvez certos tipos de referências que não são, e não há mais nenhuma diferença notacional. Uma conscélula Lisp é um par de ponteiros, embora a fixnumnão seja um ponteiro. Em Java, a variável usada para a instância de uma classe é um ponteiro, mas intnão é. A sintaxe da linguagem não reflete isso.

C é incomum, pois os ponteiros são opcionais, explícitos e permitem aritmética explícita. É perfeitamente possível escrever struct foo bar; struct foo * baz;e, depois de alocar memória, bazvocê pode usar os dois bare bazrepresentar struct foos. Como os ponteiros são opcionais, é útil ter diferenças notacionais. (É essencial em C ++ para ponteiros inteligentes, conforme indicado boost::shared_ptr<foo> bar;, bar.reset()tem um significado e bar->reset()provavelmente tem um significado muito diferente.)

(Na verdade, ponteiros explícitos costumavam ser usados ​​em outros idiomas quando o C estava sendo desenvolvido originalmente, como ^em Pascal. C é um idioma mais antigo do que o comum hoje em dia, e mostra.)

Um dos objetivos de design de C era escrever o Unix e, portanto, precisava lidar com os locais de memória de maneira detalhada. (C é realmente um de uma família de linguagens de implementação de sistema comuns quando estava sendo projetado, outro exemplo é o Cybol para computadores Control Data. C é o que se tornou um grande sucesso.) Portanto, é possível manipular os ponteiros C diretamente, atribuir endereços de memória e calcular novos. Isso também levou a algumas decisões de projeto em C. As matrizes C são baseadas fortemente na aritmética do ponteiro e, de fato, uma matriz se decompõe em um ponteiro em muitas situações. A passagem de variáveis ​​para funções C por referência é feita por ponteiro. Não havia uma forte necessidade de matrizes e de passagem de variáveis ​​por referência, na forma que outras línguas contemporâneas tinham; portanto, C não as recebeu.

Portanto, a resposta é que, na maioria dos idiomas hoje em dia, você usa ponteiros constantemente sem ser lembrado do fato. Em C e, em menor grau, em C ++, você usa ponteiros para executar tarefas de baixo nível ou realizar tarefas de nível superior para as quais não há notação especial.

David Thornley
fonte
resposta muito boa
Kate Gregory
11
Aceito esta resposta porque ela descreve melhor a diferença que não consegui entender entre ponteiros em C / C ++ e Reference em Java.
Olivers
Seria bom adicionar uma breve explicação de por que o Java não usa ponteiros para esclarecer melhor o "golpe" percebido por Gosling (principal criador do Java).
Guido Anselmi
10

Estruturas de dados complexas. Você não pode criar algo como uma lista vinculada ou uma árvore binária sem ponteiros.

Não há "prós" e "contras" de ponteiros. Eles são apenas uma ferramenta, como um martelo.

zvrba
fonte
5
Em Java, não há ponteiros. No entanto, é possível criar lista vinculada e árvore binária. Há uma diferença entre referências (como em Java) e ponteiros (como em C).
StartClass0830
7
Não há diferença entre referências e ponteiros. A aritmética do ponteiro é específica do C; existem outros idiomas que possuem ponteiros, mas não possuem aritmética para ponteiros (por exemplo, Pascal).
Zvrba
11
Ponteiros e referências não são sinônimos como você pensa. Leia isto para ver as diferenças. stackoverflow.com/questions/57483/…
StartClass0830
4
Para endereçar os dois primeiros itens dessa lista: As referências Java PODEM ser reatribuídas e PODEM apontar para nulo. A característica distintiva de um ponteiro é que permite fazer referência indireta a outro objeto. Meu teste decisivo é: se você pode construir uma estrutura circular de dados (o que você pode fazer com as referências Java), é um ponteiro. (Note que você não pode construir estrutura de dados circular com referências C ++.)
zvrba
11
Há uma diferença entre ponteiros e referências. C #, por exemplo, possui ambos . ( blogs.msdn.com/b/ericlippert/archive/2009/02/17/… )
Steven Evers
2
  • Com ponteiros, você pode alocar e desalocar memória em tempo de execução.
  • E você pode usar grandes estruturas de dados fora do escopo permitido sem serem copiadas.

Referências em C ++, Java e outros tipos de linguagens são apenas 'indicadores seguros'. E essas referências são muito usadas em Java.

Gulshan
fonte
11
Referências em C ++ NÃO são ponteiros seguros. Referências em C ++ não têm nada a ver com ponteiros. Referências em C ++ são aliases . Eles não podem ser atribuídos a NULLe não podem ser modificados após serem criados.
Billy ONeal
@ Billy: as referências C ++ geralmente são implementadas usando ponteiros e funcionam de maneira semelhante em algumas coisas, para que as pessoas continuem pensando nelas como uma espécie de ponteiro restrito.
precisa
2

Praticamente qualquer programa de computador precisa inspecionar e alterar valores na memória (conhecidos como espiar e cutucar, para aqueles que têm idade suficiente). Você precisa controlar onde estão esses valores na memória, para que o resultado seja previsível (e, em certos casos, a ordem é importante: carregar o código executável é um exemplo). Portanto, você precisa ter um tipo de dados que represente um local na memória. Mesmo que seu ambiente de programação oculte isso sob uma abstração, ele ainda estará lá.


fonte
2

char*é um exemplo ruim de ponteiros. Você provavelmente está melhor usando std::string(ou algum tipo melhor que lida com sua especialidade unicode / ansi / multibyte) do que char*. Para quase qualquer outro exemplo de ponteiros ( Employee*, PurchaseOrder*...), no entanto, há muitas vantagens:

  • escopo maior que uma única função - aloque o objeto na pilha e passe o ponteiro por um longo tempo
  • A função mais rápida exige objetos grandes, pois você não tem o custo de cópia do valor por passagem
  • uma maneira de ativar uma função para alterar os parâmetros passados ​​para ela
  • economize espaço e tempo nas coleções, copiando apenas um endereço em vez de um objeto inteiro

De fato, os ponteiros são tão importantes que a maioria dos idiomas que parecem não os possuir realmente os possui. Os tipos de referência em C # e Java são essencialmente ponteiros disfarçados de objetos sólidos.

Agora, a manipulação de ponteiros ( p++em um ponteiro ou p += delta) é uma história totalmente diferente. Algumas pessoas acham que é perigoso, outras acham ótimo. Mas isso é ainda mais longe da sua pergunta.

Kate Gregory
fonte
1

Os ponteiros podem ser mais rápidos e gerar menos sobrecarga, tanto na estrutura de dados quanto na redução da pegada de execução do programa. (Observe a palavra 'pode'.)

Em geral, a regra é que, se você alocou um recurso, executando sua própria alocação ou fazendo com que algo o faça em seu nome, é seu trabalho liberá-lo quando terminar.

O ônus de fazer isso é colocar a responsabilidade de volta no desenvolvedor, em vez de fazer com que o tempo de execução o faça. Isso tem mais algumas vantagens, pois as coisas podem durar mais tempo, atravessar fronteiras, ser descartadas em momentos mais oportunos ou não precisar carregar o peso de um coletor de lixo.

Em casos exóticos, geralmente envolvendo exceções e escopo, existem alguns casos extremos que exigem que você tenha um pouco mais de cuidado se o código que a limpeza for evitado. Realisticamente, esses casos podem ser projetados ao redor. Vivemos sem código gerenciado por muitas décadas.

Muitas vezes, o que torna os ponteiros "difíceis" simplesmente não é entender o que está acontecendo no nível do hardware. Não é nada além de indireção.

Os ponteiros oferecem muito mais acesso bruto, e isso pode ser muito útil, inteligente ou necessário. Você pode apontar para qualquer lugar e tratá-lo praticamente como qualquer coisa. Se você usa seus poderes divinos para o bem, é muito, muito bom.

O lado contrário é geralmente um desperdício, esquecendo-se de liberar algo, ou liberando-o mais de uma vez, ou referenciando-se a algo depois que ele foi lançado, ou referenciando algo quando você não está apontando para lugar nenhum. Essas coisas geralmente resultam em falhas espetaculares e, para ser honesto, geralmente são indicativas de que você tem um problema de lógica, em vez de ponteiros serem frágeis.

Se você é um desenvolvedor sólido, usar ponteiros não deve ser mais problemático do que qualquer outra estrutura de dados. Novamente, não é ciência de foguetes, e as pessoas fizeram isso por décadas sem sequer piscar um olho. É apenas ensinado menos completamente nos dias de hoje.

Tudo isso dito, a menos que você precise de indicadores, os casos de conveinência e exoíticas que uma boa coleta de lixo fornece tornam o trabalho em um ambiente gerenciado muito mais agradável. É ótimo poder recuperar um pouco de memória, usá-lo e abandoná-lo, sabendo que, algum tempo depois, pode ser descartado, se fizer sentido. Isso é um pouco menos de código da parte do codificador, em troca de um tempo de execução que faz algum levantamento extra.

Walt Stoneburner
fonte
0

A melhor resposta está realmente incluída na pergunta: os indicadores são para programação de baixo nível. É verdade que, se você estiver usando C, não usar ponteiros é como programar com uma mão amarrada nas costas, mas a resposta é usar uma linguagem de nível superior.

Larry Coleman
fonte
-1

Os ponteiros fornecem uma visibilidade da máquina necessária para a programação mais interessante. A maioria das linguagens modernas simplesmente oculta os pedacinhos de você.

Paul Nathan
fonte