Vejo em C ++ que existem várias maneiras de alocar e liberar dados e entendo que, quando você liga, malloc
deve ligar free
e quando você usa o new
operador, deve emparelhar delete
e é um erro misturar as duas (por exemplo, ligar free()
para algo que foi criado com o new
operador), mas não estou claro quando devo usar malloc
/ free
e quando devo usar new
/ delete
nos meus programas do mundo real.
Se você é um especialista em C ++, informe-me sobre quaisquer regras práticas ou convenções que você siga a esse respeito.
c++
memory-management
malloc
new-operator
JVApen
fonte
fonte
Respostas:
A menos que você seja forçado a usar C, nunca deve usá-lo
malloc
. Sempre usenew
.Se você precisar de uma grande quantidade de dados, faça algo como:
Cuidado, pois isso não está correto:
Em vez disso, você deve fazer isso ao excluir uma matriz de dados:
A
new
palavra-chave é a maneira C ++ de fazê-lo e garantirá que seu tipo tenha seu construtor chamado . Anew
palavra-chave também é mais segura para o tipo, enquantomalloc
não é segura para o tipo.A única maneira que eu poderia pensar que seria benéfico usar
malloc
seria se você precisasse alterar o tamanho do seu buffer de dados. Anew
palavra-chave não possui uma maneira análogarealloc
. Arealloc
função pode estender o tamanho de um pedaço de memória para você com mais eficiência.Vale ressaltar que você não pode misturar
new
/free
emalloc
/delete
.Nota: Algumas respostas nesta pergunta são inválidas.
fonte
new[]
seria muito mais seguro do questd::vector
? Se alguém usarnew[]
, a única maneira de o ponteiro se tornar inválido seria via explícitadelete
, enquanto a memória alocada para umstd::vector
pode ser invalidada quando o vetor é redimensionado ou sai do escopo. (Observe que, ao usarnew[]
um, seria necessário permitir a possibilidade de não chamardelete
se o método assíncrono ainda estiver pendente; se for necessário abandonar uma operação assíncrona, pode ser necessário organizar a exclusão por meio de retorno de chamada) .A resposta curta é: não use
malloc
para C ++ sem uma boa razão para fazê-lo.malloc
possui várias deficiências quando usado com C ++, quenew
foi definido para superar.Deficiências corrigidas por novo no código C ++
malloc
não é tipicamente seguro de maneira significativa. Em C ++, você deve converter o retornovoid*
. Isso potencialmente apresenta muitos problemas:É pior do que isso, no entanto. Se o tipo em questão for POD (dados antigos simples) , você poderá usar de maneira semi-sensata
malloc
para alocar memória para ele, comof2
no primeiro exemplo.Não é tão óbvio se um tipo é POD. O fato de que é possível que um determinado tipo seja alterado de POD para não-POD sem nenhum erro resultante do compilador e com problemas potencialmente muito difíceis de depurar é um fator significativo. Por exemplo, se alguém (possivelmente outro programador, durante a manutenção, muito mais tarde fizesse uma alteração que
foo
deixasse de ser POD, nenhum erro óbvio apareceria em tempo de compilação, como você esperaria, por exemplo:tornaria o
malloc
def2
ruim também tornar-se, sem qualquer diagnóstico óbvias. O exemplo aqui é trivial, mas é possível introduzir acidentalmente não-PODness muito mais longe (por exemplo, em uma classe base, adicionando um membro não-POD). Se você possui C ++ 11 / boost, podeis_pod
verificar se essa suposição está correta e gerar um erro se não estiver:Embora o impulso não possa determinar se um tipo é POD sem C ++ 11 ou outras extensões do compilador.
malloc
retornaNULL
se a alocação falhar.new
vai jogarstd::bad_alloc
. O comportamento de usar umNULL
ponteiro posteriormente é indefinido. Uma exceção possui semântica limpa quando é lançada e é lançada a partir da origem do erro. Encerrarmalloc
com um teste apropriado a cada chamada parece tedioso e propenso a erros. (Você só precisa esquecer uma vez para desfazer todo esse bom trabalho). Uma exceção pode se propagar para um nível em que um chamador é capaz de processá-la de maneira sensata, ondeNULL
é muito mais difícil retornar de forma significativa. Poderíamos estender nossasafe_foo_malloc
função para lançar uma exceção ou sair do programa ou chamar algum manipulador:Fundamentalmente,
malloc
é um recurso C enew
é um recurso C ++. Como resultado,malloc
ele não funciona bem com os construtores, mas apenas aloca um pedaço de bytes. Poderíamos estendersafe_foo_malloc
ainda mais o uso da veiculaçãonew
:Nossa
safe_foo_malloc
função não é muito genérica - idealmente, queremos algo que possa lidar com qualquer tipo, não apenasfoo
. Podemos conseguir isso com modelos e modelos variados para construtores não padrão:Agora, embora ao corrigir todos os problemas que identificamos até agora, praticamente reinventamos o
new
operador padrão . Se você vai usarmalloc
e posicionamentonew
, é melhor usarnew
para começar!fonte
struct
eclass
signifique basicamente a mesma coisa; Gostaria de saber se teria havido algum problema emstruct
ser reservado para PODs e possivelmente ter todos osclass
tipos presumidos como não-PODs. Quaisquer tipos definidos pelo código que antecederam a invenção do C ++ seriam necessariamente PODs, portanto, não acho que a compatibilidade com versões anteriores seja um problema. Existem vantagens em declarar tipos não-PODs emstruct
vez declass
?struct
eclass
fazer quase a mesma coisa foi uma decisão maravilhosa de design que agora permite um recurso interessante chamado "metaclasses" (da Herb) .$class
. Eu não tenho certeza o que isso tem a ver comclass
estruct
sendo sinônimos, no entanto.class
estruct
significar efetivamente a mesma coisa, você pode fazer transformações arbitrárias sobre eles ($class
) sem se preocupar em fazer umclass
astruct
e vice-versa.No C ++ FQA Lite :
Desculpe, eu simplesmente não pude resistir. :)
fonte
Sempre use novo em C ++. Se você precisar de um bloco de memória não digitada, poderá usar o operador new diretamente:
fonte
operator new
éoperator delete
. Não é uma ação bem definido para chamadadelete
em uma expressão com o tipovoid*
.Use
malloc
e apenas para alocar memória que será gerenciada por bibliotecas e APIs centradas em c. Use e (e as variantes) para tudo o que você controla.free
new
delete
[]
fonte
malloc
. Da mesma forma, se uma função comostrdup
precisar criar um objeto e devolvê-lo a um chamador, é perfeitamente razoável especificar que o chamador deve chamarfree
o objeto quando ele não for mais necessário. Como essas funções poderiam evitar a exposição do uso de malloc / free ao chamador?malloc
em C ++?novo vs malloc ()
1)
new
é um operador , enquantomalloc()
é uma função .2)
new
chama construtores , enquantomalloc()
não.3)
new
retorna o tipo exato de dados , enquantomalloc()
retorna nulo * .4)
new
nunca retorna um NULL (lançará em caso de falha) enquantomalloc()
retorna NULL5) A realocação de memória não tratada por
new
enquantomalloc()
podefonte
char* ptr = new (std::nothrow) char [323232];
new
funçãorealloc
e nãomalloc
e comece com sua variável de ponteiro inicializada emNULL
. Se você quiser um pedaço redimensionável de memória em C ++, por outro lado, eu estaria sugerindostd::vector
, ao contrário derealloc
... Isso ou um arquivo.Para responder sua pergunta, você deve saber a diferença entre
malloc
enew
. A diferença é simples:malloc
aloca memória , enquantonew
aloca memória E chama o construtor do objeto para o qual você está alocando memória.Portanto, a menos que você esteja restrito ao C, você nunca deve usar o malloc, especialmente ao lidar com objetos C ++. Isso seria uma receita para interromper seu programa.
Também a diferença entre
free
edelete
é a mesma. A diferença é quedelete
chamará o destruidor do seu objeto, além de liberar memória.fonte
Há uma grande diferença entre
malloc
enew
.malloc
aloca memória. Isso é bom para C, porque em C, um pedaço de memória é um objeto.No C ++, se você não está lidando com tipos de POD (que são semelhantes aos tipos C), deve chamar um construtor em um local de memória para realmente ter um objeto lá. Tipos não POD são muito comuns no C ++, pois muitos recursos do C ++ tornam um objeto automaticamente não POD.
new
aloca memória e cria um objeto nesse local de memória. Para tipos não POD, isso significa chamar um construtor.Se você fizer algo assim:
O ponteiro que você obtém não pode ser desreferenciado porque não aponta para um objeto. Você precisaria chamar um construtor antes de poder usá-lo (e isso é feito usando o posicionamento
new
).Se, por outro lado, você fizer:
Você recebe um ponteiro que é sempre válido, porque
new
criou um objeto.Mesmo para os tipos de POD, há uma diferença significativa entre os dois:
Esse trecho de código imprimiria um valor não especificado, porque os objetos POD criados por
malloc
não são inicializados.Com
new
, você pode especificar um construtor para chamar e, assim, obter um valor bem definido.Se você realmente deseja, pode usar use
new
para obter objetos POD não inicializados. Veja esta outra resposta para obter mais informações sobre isso.Outra diferença é o comportamento em caso de falha. Quando falha ao alocar memória,
malloc
retorna um ponteiro nulo, enquantonew
lança uma exceção.O primeiro exige que você teste todos os ponteiros retornados antes de usá-lo, enquanto o último sempre produzirá ponteiros válidos.
Por esses motivos, no código C ++ você deve usar
new
, e nãomalloc
. Mas, mesmo assim, você não deve usarnew
"ao ar livre", porque ele adquire os recursos que você precisa liberar mais tarde. Ao usar,new
você deve passar o resultado imediatamente para uma classe de gerenciamento de recursos:fonte
A alocação dinâmica é necessária apenas quando a vida útil do objeto deve ser diferente do escopo em que é criado (isso também é válido para tornar o escopo menor e maior) e você tem um motivo específico para armazená-lo por valor. trabalhos.
Por exemplo:
A partir do C ++ 11, temos que
std::unique_ptr
lidar com a memória alocada, que contém a propriedade da memória alocada.std::shared_ptr
foi criado para quando você precisa compartilhar a propriedade. (você precisará disso menos do que o esperado em um bom programa)Criar uma instância se torna realmente fácil:
O C ++ 17 também adiciona, o
std::optional
que pode impedir que você exija alocações de memóriaAssim que 'instância' sai do escopo, a memória é limpa. Transferir propriedade também é fácil:
Então, quando você ainda precisa
new
? Quase nunca a partir do C ++ 11. A maioria dos que você usastd::make_unique
até chegar a um ponto em que atinge uma API que transfere a propriedade por meio de ponteiros brutos.No C ++ 98/03, você precisa fazer o gerenciamento manual de memória. Se você estiver nesse caso, tente atualizar para uma versão mais recente do padrão. Se você está preso:
Certifique-se de rastrear a propriedade corretamente para não haver vazamentos de memória! A semântica de movimento também não funciona.
Então, quando precisamos de malloc em C ++? O único motivo válido seria alocar memória e inicializá-la mais tarde através do posicionamento new.
Mesmo assim, o acima exposto é válido, isso também pode ser feito através de um novo operador.
std::vector
é um bom exemplo disso.Finalmente, ainda temos o elefante na sala:
C
. Se você precisar trabalhar com uma biblioteca C em que a memória seja alocada no código C ++ e liberada no código C (ou vice-versa), você será forçado a usar o malloc / free.Se você estiver nesse caso, esqueça as funções virtuais, funções membro, classes ... Somente estruturas com PODs nele são permitidas.
Algumas exceções às regras:
fonte
Existem algumas coisas que
new
issomalloc
não funciona:new
constrói o objeto chamando o construtor desse objetonew
não requer conversão de tipo de memória alocada.Portanto, se você usar
malloc
, precisará fazer as coisas acima explicitamente, o que nem sempre é prático. Além disso,new
pode estar sobrecarregado, masmalloc
não pode estar.fonte
Se você trabalha com dados que não precisam de construção / destruição e exigem realocações (por exemplo, uma grande variedade de entradas), acredito que o malloc / free é uma boa escolha, pois fornece realloc, muito mais rápido que o new-memcpy -delete (está na minha caixa do Linux, mas acho que isso pode depender da plataforma). Se você trabalha com objetos C ++ que não são POD e requer construção / destruição, deve usar os operadores new e delete.
De qualquer forma, não vejo por que você não deveria usar os dois (desde que você libere sua memória alocada e exclua objetos alocados com novos) se puder tirar vantagem do aumento de velocidade (às vezes significativo, se estiver realocando matrizes grandes do POD) que o realloc pode fornecer.
A menos que você precise, você deve manter o novo / excluir em C ++.
fonte
Se você tiver o código C que deseja portar para o C ++, poderá deixar nele chamadas malloc (). Para qualquer novo código C ++, eu recomendo usar new.
fonte
Se você estiver usando C ++, tente usar new / delete em vez de malloc / calloc, pois são operadores. Para malloc / calloc, você precisa incluir outro cabeçalho. Não misture dois idiomas diferentes no mesmo código. O trabalho deles é semelhante em todos os aspectos: ambos alocam memória dinamicamente do segmento de heap na tabela de hash.
fonte
new
inicializará os valores padrão da estrutura e vinculará corretamente as referências nela.Por exemplo
Portanto
new struct test_s
, retornará uma estrutura inicializada com uma referência de trabalho, enquanto a versão em malloc'ed não possui valores padrão e as referências internas não são inicializadas.fonte
De uma perspectiva mais baixa, new inicializará toda a memória antes de fornecer a memória, enquanto o malloc manterá o conteúdo original da memória.
fonte
No cenário a seguir, não podemos usar new, pois ele chama construtor.
fonte
As
new
edelete
os operadores podem operar em classes e estruturas, enquantomalloc
efree
só trabalhar com blocos de memória que precisam ser fundido.O uso
new/delete
ajudará a melhorar seu código, pois você não precisará converter a memória alocada na estrutura de dados necessária.fonte
Caso raro a considerar usar malloc / free em vez de new / delete é quando você está alocando e realocando (tipos simples de pod, não objetos) usando realloc, pois não há função semelhante à realloc no C ++ (embora isso possa ser feito usando um mais abordagem C ++).
fonte
malloc () é usado para atribuir memória dinamicamente em C, enquanto o mesmo trabalho é feito por new () em c ++. Portanto, você não pode misturar convenções de codificação de 2 idiomas. Seria bom se você pedisse diferença entre calloc e malloc ()
fonte
malloc
em C ++.