É seguro excluir um ponteiro NULL?
E é um bom estilo de codificação?
c++
pointers
memory-management
null-pointer
delete-operator
qiuxiafei
fonte
fonte
delete
. Use RAII em vez disso. Ou seja, use emstd::vector<T> v(100);
vez deT* p = new T[100];
usar ponteiros inteligentes comounique_ptr<T>
eshared_ptr<T>
que cuidam da exclusão em vez de ponteiros brutos etc.make_shared
(c ++ 11) emake_unique
(c ++ 14) o programa deve conter de zero denew
edelete
new
oudelete
. As classes projetadas para gerenciar recursos, onde os componentes Standard não podem fazer o trabalho, podem, é claro, fazer o que precisam, mas o ponto é que eles fazem coisas feias com a memória que gerenciam, não com o código do usuário final. Portanto, crie sua própria classe library / helper para fazernew
/delete
e use essa classe em vez delas.Respostas:
delete
executa a verificação de qualquer maneira; portanto, verificá-la do seu lado aumenta a sobrecarga e fica mais feia. Uma prática muito boa é definir o ponteiro para NULL depoisdelete
(ajuda a evitar a exclusão dupla e outros problemas semelhantes de corrupção de memória).Eu também adoraria se,
delete
por padrão, estava definindo o parâmetro como NULL, como em(Eu sei sobre os valores de R e L, mas não seria bom?)
fonte
Do rascunho C ++ 0x Standard.
Obviamente, ninguém faria 'delete' de um ponteiro com valor NULL, mas é seguro fazê-lo. Idealmente, não se deve ter código que exclua um ponteiro NULL. Mas às vezes é útil quando a exclusão de ponteiros (por exemplo, em um contêiner) acontece em um loop. Como a exclusão de um valor de ponteiro NULL é segura, pode-se realmente escrever a lógica de exclusão sem verificações explícitas para que o operando NULL seja excluído.
Como um aparte, o C Standard $ 7.20.3.2 também diz que 'free' em um ponteiro NULL não faz nenhuma ação.
fonte
Sim, é seguro.
Não há mal em excluir um ponteiro nulo; muitas vezes reduz o número de testes no final de uma função se os ponteiros não alocados forem inicializados em zero e simplesmente excluídos.
Como a frase anterior causou confusão, um exemplo - que não é seguro para exceções - do que está sendo descrito:
Existem todos os tipos de lêndeas que podem ser selecionadas com o código de exemplo, mas o conceito (espero) é claro. As variáveis do ponteiro são inicializadas em zero, para que as
delete
operações no final da função não precisem testar se são não nulas no código-fonte; o código da biblioteca executa essa verificação de qualquer maneira.fonte
void func(void) { X *x1 = 0; Y *y1 = 0; … x1 = new[10] X; … y1 = new[10] Y; … delete[] y1; delete[] x1; }
. Eu não mostrei nenhuma estrutura de bloco ou saltos, mas asdelete[]
operações no final são seguras devido às inicializações no início. Se algo que saltou para o final apósx1
foi alocado e antesy1
foi alocado e não houve inicializaçãoy1
, haveria um comportamento indefinido - e, embora o código possa testar a nulidade (dex1
ey1
) antes das exclusões, não há necessidade de fazer tão.A exclusão de um ponteiro nulo não tem efeito. Não é um bom estilo de codificação necessariamente porque não é necessário, mas também não é ruim.
Se você estiver procurando por boas práticas de codificação, considere o uso de ponteiros inteligentes, então você não precisa
delete
.fonte
Para complementar a resposta de ruslik , no C ++ 14 você pode usar esta construção:
fonte
É seguro, a menos que você tenha sobrecarregado o operador de exclusão. se você sobrecarregou o operador de exclusão e não manipulou a condição nula, ele não é seguro.
fonte
Eu tenho experimentado que é não segura (VS2010) para excluir [] NULL (ie variedade de sintaxe). Não tenho certeza se isso está de acordo com o padrão C ++.
Ele é seguro para NULL delete (sintaxe escalar).
fonte
delete[] NULL
.