Em que casos eu uso malloc e / ou novo?


479

Vejo em C ++ que existem várias maneiras de alocar e liberar dados e entendo que, quando você liga, mallocdeve ligar freee quando você usa o newoperador, deve emparelhar deletee é um erro misturar as duas (por exemplo, ligar free()para algo que foi criado com o newoperador), mas não estou claro quando devo usar malloc/ freee quando devo usar new/ deletenos 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.


33
Gostaria apenas de adicionar um lembrete de que você não pode misturar os dois estilos - ou seja, não é possível usar new para criar um objeto e depois chamar free (), nem tentar excluir um bloco alocado por malloc (). Provavelmente óbvio dizer isso, mas mesmo assim ...
nsayer

32
Boas respostas, tudo o que tenho a acrescentar (que não vi) é que new / delete chama o construtor / destruidor para você, o malloc / free não. Apenas uma diferença que vale a pena mencionar.
Bill K

Com o C ++ moderno, ainda estou tentando encontrar um motivo para usá-lo.
Rahly

Ou use nenhum e vá com std: shared_ptr <T>. Então você não precisa excluir nada.
26418 Vincent Vincent

Respostas:


387

A menos que você seja forçado a usar C, nunca deve usá-lomalloc . Sempre use new.

Se você precisar de uma grande quantidade de dados, faça algo como:

char *pBuffer = new char[1024];

Cuidado, pois isso não está correto:

//This is incorrect - may delete only one element, may corrupt the heap, or worse...
delete pBuffer;

Em vez disso, você deve fazer isso ao excluir uma matriz de dados:

//This deletes all items in the array
delete[] pBuffer;

A newpalavra-chave é a maneira C ++ de fazê-lo e garantirá que seu tipo tenha seu construtor chamado . A newpalavra-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 mallocseria se você precisasse alterar o tamanho do seu buffer de dados. A newpalavra-chave não possui uma maneira análoga realloc. A reallocfunçã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/ freee malloc/ delete.

Nota: Algumas respostas nesta pergunta são inválidas.

int* p_scalar = new int(5);  // Does not create 5 elements, but initializes to 5
int* p_array  = new int[5];  // Creates 5 elements

2
Com relação à chamada delete foo quando você deve chamar delete [] foo, alguns compiladores corrigem isso automaticamente para você e não vazam, enquanto outros excluem apenas a primeira entrada e o vazamento. Eu tinha alguns desses em algum código e o valgrind os encontrará para você.
KPexEA 8/08

30
Se você não usar a exclusão correta, o resultado será indefinido . Está incorreto. O fato de que pode acertar parte da coisa ou funcionar algumas vezes é apenas sorte cega.
Michael Burr

8
@KPexEA: Mesmo que alguns compiladores possam corrigir seus erros, ainda é errado cometê-los em primeiro lugar :) Sempre use delete [] quando apropriado.
9138 korona

62
"A menos que você seja forçado a usar C, você nunca deve usar malloc. Sempre use novo." Por quê? Qual é a vitória aqui? Para objetos que precisamos de construção, mas para blocos de memória, você documenta claramente duas maneiras de cometer erros de codificação (o mais facilmente capturado () vs [] no novo e o array incompatível menos facilmente capturado versus o scaler new e delete). Qual é a motivação para usar new / delete para blocos de memória bruta?
Ben Supnik

3
@DeadMG: se alguém estiver criando uma matriz para uso por uma função de API assíncrona, não new[] seria muito mais seguro do que std::vector? Se alguém usar new[], a única maneira de o ponteiro se tornar inválido seria via explícita delete, enquanto a memória alocada para um std::vectorpode ser invalidada quando o vetor é redimensionado ou sai do escopo. (Observe que, ao usar new[]um, seria necessário permitir a possibilidade de não chamar deletese 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) .
supercat

144

A resposta curta é: não use mallocpara C ++ sem uma boa razão para fazê-lo. mallocpossui várias deficiências quando usado com C ++, que newfoi definido para superar.

Deficiências corrigidas por novo no código C ++

  1. mallocnão é tipicamente seguro de maneira significativa. Em C ++, você deve converter o retorno void*. Isso potencialmente apresenta muitos problemas:

    #include <stdlib.h>
    
    struct foo {
      double d[5];
    }; 
    
    int main() {
      foo *f1 = malloc(1); // error, no cast
      foo *f2 = static_cast<foo*>(malloc(sizeof(foo)));
      foo *f3 = static_cast<foo*>(malloc(1)); // No error, bad
    }
  2. É pior do que isso, no entanto. Se o tipo em questão for POD (dados antigos simples) , você poderá usar de maneira semi-sensata mallocpara alocar memória para ele, como f2no 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 foodeixasse de ser POD, nenhum erro óbvio apareceria em tempo de compilação, como você esperaria, por exemplo:

    struct foo {
      double d[5];
      virtual ~foo() { }
    };

    tornaria o mallocde f2ruim 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, pode is_podverificar se essa suposição está correta e gerar um erro se não estiver:

    #include <type_traits>
    #include <stdlib.h>
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      return static_cast<foo*>(malloc(sizeof(foo)));
    }

    Embora o impulso não possa determinar se um tipo é POD sem C ++ 11 ou outras extensões do compilador.

  3. malloc retorna NULL se a alocação falhar. newvai jogar std::bad_alloc. O comportamento de usar um NULLponteiro posteriormente é indefinido. Uma exceção possui semântica limpa quando é lançada e é lançada a partir da origem do erro. Encerrar malloccom 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, onde NULLé muito mais difícil retornar de forma significativa. Poderíamos estender nossa safe_foo_mallocfunção para lançar uma exceção ou sair do programa ou chamar algum manipulador:

    #include <type_traits>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      foo *mem = static_cast<foo*>(malloc(sizeof(foo)));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return mem;
    }
  4. Fundamentalmente, mallocé um recurso C e newé um recurso C ++. Como resultado, mallocele não funciona bem com os construtores, mas apenas aloca um pedaço de bytes. Poderíamos estender safe_foo_mallocainda mais o uso da veiculação new:

    #include <stdlib.h>
    #include <new>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      void *mem = malloc(sizeof(foo));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return new (mem)foo();
    }
  5. Nossa safe_foo_mallocfunção não é muito genérica - idealmente, queremos algo que possa lidar com qualquer tipo, não apenas foo. Podemos conseguir isso com modelos e modelos variados para construtores não padrão:

    #include <functional>
    #include <new>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    template <typename T>
    struct alloc {
      template <typename ...Args>
      static T *safe_malloc(Args&&... args) {
        void *mem = malloc(sizeof(T));
        if (!mem) {
           my_malloc_failed_handler();
           // or throw ...
        }
        return new (mem)T(std::forward(args)...);
      }
    };

    Agora, embora ao corrigir todos os problemas que identificamos até agora, praticamente reinventamos o newoperador padrão . Se você vai usar malloce posicionamento new, é melhor usarnew para começar!


27
É uma pena que o C ++ tenha sido feito structe classsignifique basicamente a mesma coisa; Gostaria de saber se teria havido algum problema em structser reservado para PODs e possivelmente ter todos os classtipos 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 em structvez de class?
Supercat

1
@supercat Um pouco tarde, mas, como se sabe , fazer structe classfazer quase a mesma coisa foi uma decisão maravilhosa de design que agora permite um recurso interessante chamado "metaclasses" (da Herb) .
Rakete1111

@ Rakete1111: À primeira vista, essa proposta parece pré-processar uma versão do idioma que usa palavras-chave com prefixo em dólar $class. Eu não tenho certeza o que isso tem a ver com classe structsendo sinônimos, no entanto.
Supercat

@supercat O sistema de tipos teria sido mais bifurcado. Por ter classe structsignificar efetivamente a mesma coisa, você pode fazer transformações arbitrárias sobre eles ( $class) sem se preocupar em fazer um classa structe vice-versa.
precisa saber é o seguinte

@ Rakete1111: Se certos tipos de operações e transformações são seguras em alguns tipos, mas não em outros, o tipo diretamente identifica isso e o compilador rejeita operações e transformações inseguras, seria melhor do que alterar uma metaclasse usada em de maneiras adequadas apenas para um PODS, mude silenciosamente para um não PODS.
Supercat

53

No C ++ FQA Lite :

[16.4] Por que devo usar malloc antigo novo e não confiável ()?

FAQ: new / delete chama o construtor / destruidor; novo é do tipo seguro, malloc não é; new pode ser substituído por uma classe.

FQA: As virtudes das novidades mencionadas no FAQ não são virtudes, porque construtores, destruidores e sobrecarga de operadores são lixo (veja o que acontece quando você não tem coleta de lixo?), E o problema de segurança de tipo é realmente pequeno aqui (normalmente você tem para converter o void * retornado por malloc no tipo de ponteiro correto para atribuí-lo a uma variável de ponteiro digitada, o que pode ser irritante, mas longe de ser "inseguro").

Ah, e o uso de malloc antigo confiável torna possível usar o realloc igualmente confiável e antigo. Pena que não temos um novo operador brilhante renovado ou algo assim.

Ainda assim, new não é ruim o suficiente para justificar um desvio do estilo comum usado em uma linguagem, mesmo quando a linguagem é C ++. Em particular, as classes com construtores não triviais se comportarão de maneira fatal se você simplesmente fizer mal aos objetos. Então, por que não usar new em todo o código? As pessoas raramente sobrecarregam o operador novo, por isso provavelmente não atrapalha muito o seu caminho. E se eles sobrecarregarem de novo, você sempre pode pedir para eles pararem.

Desculpe, eu simplesmente não pude resistir. :)


7
Isso é um tumulto ! Obrigado.
dmckee --- ex-moderador gatinho

8
Não posso levar esse comentário a sério, pois projeta claramente a tendência do autor contra o C ++. C ++ é uma linguagem usada para criar software orientado ao desempenho, e um coletor de lixo só pode ser prejudicial a seu objetivo. Discordo de toda a sua resposta!
Miguel

1
@ Miguel Você perdeu a piada.
precisa saber é o seguinte

50

Sempre use novo em C ++. Se você precisar de um bloco de memória não digitada, poderá usar o operador new diretamente:

void *p = operator new(size);
   ...
operator delete(p);

3
interessante, eu sempre acabei de alocar uma matriz de caracteres não assinados quando preciso de um buffer de dados brutos como este.
Greg Rogers

Cuidado, a semântica deve ser assim: p_var = novo tipo (inicializador); Não tamanho.
Brian R. Bondy

11
Não se você chamar o operador de novo diretamente, será necessário o número de bytes para alocar como parâmetro.
Ferruccio

1
Hrm não tenho certeza, nunca ouvi falar dessa sintaxe.
Brian R. Bondy

9
O oposto de operator newé operator delete. Não é uma ação bem definido para chamada deleteem uma expressão com o tipo void*.
CB Bailey

33

Use malloce 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 newdelete[]


10
Observe também que uma biblioteca C bem escrita esconderá malloc e será liberada internamente; é assim que o programador C deve funcionar.
Dacav

@dmckee você tem um exemplo de C ++ usando bibliotecas centradas em c por malloc e free?
milesma 31/07

1
@Dacav: Se uma função C aceitar um ponteiro para um objeto que ele precisará continuar usando após o retorno da função, e o chamador não terá como saber quando o objeto ainda é necessário, seria perfeitamente razoável para a função para especificar que o ponteiro deve ter sido criado com malloc. Da mesma forma, se uma função como strdupprecisar criar um objeto e devolvê-lo a um chamador, é perfeitamente razoável especificar que o chamador deve chamar freeo 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?
Supercat

@ supercat, há algo inerentemente errado em ter uma função C aceitar um ponteiro para objetos, já que C não está ciente dos objetos. Em geral, acredito que a melhor abordagem é ter invólucros semânticos em torno da alocação / desalocação também em C. Ainda pode ser aceitável, mas menos flexível, se uma biblioteca C estiver solicitando que o chamador pré-aloque e / ou desaloque a memória. Se uma função C estiver fazendo isso e reivindicando propriedade na memória alocada, você precisará implicitamente alocá-la com malloc.
Dacav 06/04/2015

@supercat Um exemplo de um pacote diário que eu tenho certeza que todo mundo usou é o libgmp. Se você já usou alguma criptografia de código aberto ou software baseado nessa criptografia (o que é muito provável), provavelmente usou uma biblioteca aritmética de precisão arbitrária que precisa aumentar e reduzir seus próprios dados internos. Isso é feito usando uma função de inicialização ... e então você se pergunta: como você usa o código C que é libgmp, em C ++, sem recompilá-lo em C ++? Agora, com isso (o vinculador) em mente, pense nisso ... por que uma pessoa sensata jamais colocaria mallocem C ++?
Autistic

31

novo vs malloc ()

1) newé um operador , enquanto malloc()é uma função .

2) newchama construtores , enquanto malloc()não.

3) newretorna o tipo exato de dados , enquanto malloc()retorna nulo * .

4) newnunca retorna um NULL (lançará em caso de falha) enquanto malloc()retorna NULL

5) A realocação de memória não tratada por newenquanto malloc()pode


6
Olá, Para o ponto 4), o novo pode ser instruído a retornar NULL em caso de falha. char* ptr = new (std::nothrow) char [323232];
Singh

1
6) new cria a partir de argumentos do construtor, enquanto malloc usa tamanho.
Evan Moran

há também uma newfunção
Ma Ming

Se você estivesse tão inclinado em C para se realocar , eu espero que você use realloce não malloce comece com sua variável de ponteiro inicializada em NULL. Se você quiser um pedaço redimensionável de memória em C ++, por outro lado, eu estaria sugerindo std::vector, ao contrário de realloc... Isso ou um arquivo.
Autistic

19

Para responder sua pergunta, você deve saber a diferença entre mallocenew . A diferença é simples:

malloc aloca memória , enquanto new 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 freee deleteé a mesma. A diferença é que deletechamará o destruidor do seu objeto, além de liberar memória.


13

Há uma grande diferença entre malloce new.mallocaloca 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.

newaloca 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:

non_pod_type* p = (non_pod_type*) malloc(sizeof *p);

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:

non_pod_type* p = new non_pod_type();

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:

pod_type* p = (pod_type*) malloc(sizeof *p);
std::cout << p->foo;

Esse trecho de código imprimiria um valor não especificado, porque os objetos POD criados por mallocnão são inicializados.

Com new, você pode especificar um construtor para chamar e, assim, obter um valor bem definido.

pod_type* p = new pod_type();
std::cout << p->foo; // prints 0

Se você realmente deseja, pode usar use newpara 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, mallocretorna um ponteiro nulo, enquanto newlanç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ão malloc. Mas, mesmo assim, você não deve usar new"ao ar livre", porque ele adquire os recursos que você precisa liberar mais tarde. Ao usar, newvocê deve passar o resultado imediatamente para uma classe de gerenciamento de recursos:

std::unique_ptr<T> p = std::unique_ptr<T>(new T()); // this won't leak

7

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:

 std::vector<int> *createVector(); // Bad
 std::vector<int> createVector();  // Good

 auto v = new std::vector<int>(); // Bad
 auto result = calculate(/*optional output = */ v);
 auto v = std::vector<int>(); // Good
 auto result = calculate(/*optional output = */ &v);

A partir do C ++ 11, temos que std::unique_ptrlidar com a memória alocada, que contém a propriedade da memória alocada.std::shared_ptrfoi 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:

auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::make_unique<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::make_unique<Class[]>(new Class[](42)); // C++11

O C ++ 17 também adiciona, o std::optionalque pode impedir que você exija alocações de memória

auto optInstance = std::optional<Class>{};
if (condition)
    optInstance = Class{};

Assim que 'instância' sai do escopo, a memória é limpa. Transferir propriedade também é fácil:

 auto vector = std::vector<std::unique_ptr<Interface>>{};
 auto instance = std::make_unique<Class>();
 vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)

Então, quando você ainda precisa new? Quase nunca a partir do C ++ 11. A maioria dos que você usa std::make_uniqueaté chegar a um ponto em que atinge uma API que transfere a propriedade por meio de ponteiros brutos.

 auto instance = std::make_unique<Class>();
 legacyFunction(instance.release()); // Ownership being transferred

 auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr

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:

 auto instance = new Class(); // Allocate memory
 delete instance;             // Deallocate
 auto instances = new Class[42](); // Allocate memory
 delete[] instances;               // Deallocate

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.

 auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
 auto instance = new(instanceBlob)Class{}; // Initialize via constructor
 instance.~Class(); // Destroy via destructor
 std::free(instanceBlob); // Deallocate the memory

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:

  • Você está escrevendo uma biblioteca padrão com estruturas de dados avançadas onde o malloc é apropriado
  • Você precisa alocar grandes quantidades de memória (na cópia de memória de um arquivo de 10 GB?)
  • Você tem ferramentas impedindo o uso de certas construções
  • Você precisa armazenar um tipo incompleto

6

Existem algumas coisas que newisso mallocnão funciona:

  1. new constrói o objeto chamando o construtor desse objeto
  2. new não requer conversão de tipo de memória alocada.
  3. Ele não requer que uma quantidade de memória seja alocada, mas requer que vários objetos sejam construídos.

Portanto, se você usar malloc, precisará fazer as coisas acima explicitamente, o que nem sempre é prático. Além disso, newpode estar sobrecarregado, mas mallocnão pode estar.


5

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 ++.


3

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.


3

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.


2

new inicializará os valores padrão da estrutura e vinculará corretamente as referências nela.

Por exemplo

struct test_s {
    int some_strange_name = 1;
    int &easy = some_strange_name;
}

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.


1

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.


4
O novo geralmente não inicializa a memória, embora haja maneiras de fazer isso acontecer: consulte stackoverflow.com/questions/2204176/… para obter uma discussão sobre isso.
WJL

0

No cenário a seguir, não podemos usar new, pois ele chama construtor.

class  B  {
private:
    B *ptr;
    int x;
public:
    B(int n)  {
        cout<<"B: ctr"<<endl;
        //ptr = new B;  //keep calling ctr, result is segmentation fault
        ptr = (B *)malloc(sizeof(B));
        x = n;
        ptr->x = n + 10;
    }
    ~B()  {
        //delete ptr;
        free(ptr);
        cout<<"B: dtr"<<endl;
    }
};

0

As newe deleteos operadores podem operar em classes e estruturas, enquanto malloce freesó trabalhar com blocos de memória que precisam ser fundido.

O uso new/deleteajudará a melhorar seu código, pois você não precisará converter a memória alocada na estrutura de dados necessária.


0

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 ++).


-4

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 ()


2
Você pode (mas quase sempre não deveria) usar mallocem C ++.
26412 interjay

1
Você também perdeu o ponto principal que deveria ter como objetivo evitar a alocação dinâmica de memória, a menos que isso seja feito através de indicadores inteligentes. Você está apenas definindo sua auto-se para a dor outro sábio
thecoshman
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.