Li em algum lugar que, ao usar C ++, é recomendável não usar ponteiros. Por que os ponteiros são uma péssima idéia quando você está usando C ++. Para programadores C que estão acostumados a usar ponteiros, qual é a melhor alternativa e abordagem em C ++?
45
NetConnection
instâncias desconectadas do servidor ( stackoverflow.com/questions/14780456/… ), além de um problema de haver vários objetos em um programa que ele se recusará especificamente a coletar. ...GCRoots are never garbage collected.
e o parágrafo iniciado porThe MMgc is considered a conservative collector for mark/sweep.
). Tecnicamente, esse é um problema no Adobe Virtual Machine 2, não no AS3, mas quando você tem problemas como esse em idiomas de nível superior, com coleta de lixo essencialmente incorporada, geralmente não há uma maneira verdadeira de depurar o idioma. essas questões completamente fora do programa. ...Respostas:
Eu acho que eles significam que você deve usar ponteiros inteligentes em vez de ponteiros regulares.
Em C ++, a ênfase seria na coleta de lixo e na prevenção de vazamentos de memória (apenas para citar dois). Os ponteiros são uma parte fundamental da linguagem, portanto, não é impossível usá-los, exceto nos programas mais trivalentes.
fonte
Já que publiquei a polêmica “não use ponteiros de merda” , sinto que devo comentar aqui.
Antes de tudo, como polêmica, obviamente representa um ponto de vista extremo. Não são definitivamente usos legítimos de ponteiros (matérias). Mas eu (e muitos programadores profissionais de C ++) sustentamos que esses casos são extremamente raros. Mas o que realmente queremos dizer é o seguinte:
Primeiro:
Aqui, “própria memória” significa essencialmente que em algum momento
delete
é chamado nesse ponteiro (mas é mais geral que isso). Esta declaração pode ser tomada com segurança como absoluta. A única exceção é ao implementar seu próprio ponteiro inteligente (ou outra estratégia de gerenciamento de memória). E mesmo lá, você normalmente ainda deve usar um ponteiro inteligente em nível baixo.A lógica para isso é bastante simples: ponteiros brutos que possuem memória introduzem uma fonte de erro. E esses erros são prolíficos no software existente: vazamentos de memória e exclusão dupla - ambos uma consequência direta da propriedade pouco clara dos recursos (mas indo na direção oposta).
Esse problema pode ser completamente eliminado, praticamente sem nenhum custo, simplesmente usando ponteiros inteligentes em vez de ponteiros brutos (ressalva: isso ainda requer pensamento, é claro; ponteiros compartilhados podem levar a ciclos e, portanto, mais uma vez a vazamentos de memória - mas isso é facilmente evitável).
Segundo:
Diferente de outras linguagens, o C ++ tem um suporte muito forte à semântica de valores e simplesmente não precisa da indireta de ponteiros. Isso não foi percebido imediatamente - historicamente, o C ++ foi inventado para facilitar a orientação fácil de objetos em C e dependia muito da construção de gráficos de objetos conectados por ponteiros. Mas no C ++ moderno, esse paradigma raramente é a melhor escolha, e os idiomas modernos do C ++ geralmente não precisam de ponteiros . Eles operam com valores e não com indicadores.
Infelizmente, essa mensagem ainda não foi capturada em grande parte da comunidade de usuários do C ++. Como resultado, a maior parte do código C ++ que está escrito ainda está repleta de ponteiros supérfluos que tornam o código complexo, lento e com defeito / não confiável.
Para alguém que sabe moderna C ++, é claro que você muito raramente precisam de quaisquer ponteiros (quer inteligentes ou matérias; exceto quando usá-los como iteradores). O código resultante é mais curto, menos complexo, mais legível, geralmente mais eficiente e mais confiável.
fonte
std::unique_ptr
. Além disso, por que nãoptr_vec
? Mas geralmente um vetor de valor ainda será trocado mais rapidamente (especialmente com a semântica de movimentação).boost::variant
com arecursive_wrapper
é provavelmente a minha solução favorita para representar um DAG.Simplesmente porque existem abstrações disponíveis que ocultam os aspectos mais temperamentais do uso de ponteiros, como acesso à memória não processada e limpeza após as alocações. Com ponteiros inteligentes, classes de contêiner e padrões de design como RAII, a necessidade de usar ponteiros brutos é diminuída. Dito isto, como qualquer abstração, você deve entender como eles realmente funcionam antes de ir além deles.
fonte
Relativamente simples, a mentalidade C é "Você tem um problema? Use um ponteiro". Você pode ver isso em cadeias C, ponteiros de função, ponteiros como iteradores, ponteiro para ponteiro, ponteiro nulo - mesmo nos primeiros dias do C ++ com ponteiros membros.
Mas em C ++ você pode usar valores para muitas ou todas essas tarefas. Precisa de uma abstração de função?
std::function
. É um valor que é uma função.std::string
? É um valor, é uma string. Você pode ver abordagens semelhantes em todo o C ++. Isso torna a análise do código muito mais fácil para humanos e compiladores.fonte
Um dos motivos é a aplicação muito ampla de ponteiros. Eles podem ser usados para iteração em contêineres, para evitar a cópia de objetos grandes ao passar para a função, gerenciamento não trivial do tempo de vida, acesso a lugares aleatórios na memória, etc. imediatamente independentemente da intenção.
A seleção de uma ferramenta para fins exatos torna o código mais simples e mais visível - iteradores para iterações, indicadores inteligentes para gerenciamento de toda a vida útil, etc.
fonte
Além dos motivos já listados, existe um óbvio: melhores otimizações. A análise de aliasing é muito complicada na presença de uma aritmética de ponteiro, enquanto as referências sugerem um otimizador, portanto, uma análise de aliasing muito mais profunda é possível se apenas referências forem usadas.
fonte
Além do risco de vazamento de memória declarado pelo @jmquigley, a ponteiro e a aritmética do ponteiro podem ser consideradas problemáticas porque os ponteiros podem apontar para qualquer lugar da memória, causando "erros difíceis de encontrar" e "vulnerabilidades de segurança".
É por isso que eles foram quase abandonados em C # e Java.
fonte
unsafe
palavra-chaveO C ++ suporta a maioria dos recursos C , além de Objetos e Classes. C já tinha ponteiros e outras coisas.
Os ponteiros são uma técnica muito útil, que pode ser combinada com a Orientação a objetos, e o C ++ os suporta. Porém, essa técnica é difícil de ensinar e difícil de entender e é muito fácil causar erros indesejados.
Muitas novas linguagens de programação fingem não usar ponteiros com objetos, como Java, .NET, Delphi, Vala, PHP, Scala. Mas, ponteiros ainda são usados "nos bastidores". Essas técnicas de "ponteiro oculto" são chamadas de "referências".
Enfim, considero o (s) ponteiro (s) como um Padrão de Programação, como uma maneira válida de resolver certos problemas, assim como a Programação Orientada a Objetos .
Outros desenvolvedores podem ter uma opinião diferente. Mas sugiro que estudantes e programadores aprendam como:
(1) Use ponteiros sem objetos
(2) objetos sem ponteiros
(3) ponteiros explícitos para objetos
(4) ponteiros "ocultos" para objetos ( referência AKA ) ;-)
Naquela ordem.
Mesmo que seja difícil de ensinar e difícil de aprender. O objeto Pascal (Delphi, FreePascal, outros) e
C++
(não Java ou C #) pode ser usado para esses objetivos.E, mais tarde, programadores iniciantes, podem passar para "ponteiros ocultos para objetos" linguagens de programação como: Java, C #, PHP orientado a objetos e outros.
fonte
Falando sobre o VC6, quando você lança um ponteiro de uma classe (que você instancia) em uma variável (por exemplo, DWORD), mesmo que esse ponteiro seja local, você pode acessar a classe por todas as funções que usam o mesmo heap. A classe instanciada é definida como local, mas na verdade não é. Até onde eu sei, qualquer endereço de uma variável, estrutura ou classe de pilha é único ao longo de toda a vida útil da classe de hospedagem.
Exemplo:
EDIT Isso é uma parte muito pequena do código original. A classe CSRecodset é apenas uma classe de conversão de CXdbRecordset, onde está todo o código real. Fazendo isso, posso permitir que o usuário se beneficie do que escrevi sem perder meus direitos. Não pretendo demonstrar que meu mecanismo de banco de dados é profissional, mas realmente funciona.
EDIT: solicitado por DeadMG:
fonte
DWORD
é abusiva e possivelmente incorreta (DWORD não é necessariamente grande o suficiente para segurar um ponteiro). Se você precisar de um ponteiro não digitado, usevoid*
- mas, quando precisar disso em C ++, geralmente terá um problema de design em seu código, que deverá corrigir.