Como inicializar a memory com o novo operador em C ++?

Eu só estou começando a entrar no C ++ e quero pegar alguns bons hábitos. Se eu tiver acabado de alocar uma matriz do tipo int com o new operador, como posso inicializá-los todos como 0 sem fazer o loop de todos eles sozinho? Devo usar apenas memset ? Existe uma maneira “C ++” de fazer isso?

É uma característica surpreendentemente pouco conhecida do C ++ (como evidenciado pelo fato de que ninguém deu isso como uma resposta ainda), mas na verdade tem syntax especial para inicializar por padrão um array (bem, tecnicamente, ele é chamado de “value- inicializar “no padrão):

 new int[10](); 

Note que você deve usar os parênteses vazios – você não pode, por exemplo, usar (0) ou qualquer outra expressão (é por isso que isso é útil somente para boot padrão).

Isto é explicitamente permitido pelo ISO C ++ 03 5.3.4 [expr.new] / 15, que diz:

Uma nova expressão que cria um object do tipo T inicializa esse object da seguinte maneira:

  • Se o novo inicializador for da forma (), o item será inicializado por valor (8.5);

e não restringe os tipos para os quais isso é permitido, enquanto o formulário (expression-list) é explicitamente restringido por regras adicionais na mesma seção, de modo que não permita tipos de array.

Assumindo que você realmente quer um array e não um std :: vector, o “jeito C ++” seria esse

 #include  int* array = new int[n]; // Assuming "n" is a pre-existing variable std::fill_n(array, n, 0); 

Mas esteja ciente de que, no fundo, isso ainda é apenas um loop que atribui cada elemento a 0 (realmente não há outra maneira de fazer isso, exceto uma arquitetura especial com suporte em nível de hardware).

Há um número de methods para alocar uma matriz de tipo intrínseco e todos esses methods estão corretos, embora qual deles escolher, depende …

Inicialização manual de todos os elementos em loop

 int* p = new int[10]; for (int i = 0; i < 10; i++) { p[i] = 0; } 

Usando a function std::memset de

 int* p = new int[10]; std::memset(p, 0, 10); 

Usando o algoritmo std::fill_n de

 int* p = new int[10]; std::fill_n(p, 10, 0); 

Usando std::vector container

 std::vector v(10); // elements zero'ed 

Se C ++ 0x disponível, usando resources de lista de inicializador

 int a[] = { 1, 2, 3 }; // 3-element static size array vector v = { 1, 2, 3 }; // 3-element array but vector is resizeable in runtime 

Se a memory que você está alocando for uma class com um construtor que faz algo útil, o operador new chamará esse construtor e deixará seu object inicializado.

Mas se você está alocando um POD ou algo que não tem um construtor que inicializa o estado do object, então você não pode alocar memory e inicializar essa memory com o operador new em uma operação. No entanto, você tem várias opções:

1) Use uma variável de pilha. Você pode alocar e inicializar por padrão em uma única etapa, da seguinte forma:

 int vals[100] = {0}; // first element is a matter of style 

2) use memset() . Note que se o object que você está alocando não for um POD , memsetting é uma má idéia. Um exemplo específico é que se você configurar uma class que tenha funções virtuais, você eliminará a vtable e deixará seu object em um estado inutilizável.

3) Muitos sistemas operacionais têm chamadas que fazem o que você deseja – alocar em um heap e inicializar os dados para algo. Um exemplo do Windows seria VirtualAlloc()

4) Esta é geralmente a melhor opção. Evite ter que gerenciar a memory por conta própria. Você pode usar contêineres STL para fazer praticamente qualquer coisa que você faria com a memory bruta, incluindo a alocação e a boot de todos de uma só vez:

 std::vector myInts(100, 0); // creates a vector of 100 ints, all set to zero 

Sim existe:

 std::vector vec(SIZE, 0); 

Use um vetor em vez de uma matriz alocada dinamicamente. Os benefícios incluem não ter que se preocupar em excluir explicitamente o array (ele é excluído quando o vetor sai do escopo) e também que a memory é automaticamente excluída mesmo se houver uma exceção lançada.

Editar: Para evitar mais votos diretos de pessoas que não se importam em ler os comentários abaixo, devo deixar mais claro que essa resposta não diz que o vetor é sempre a resposta certa. Mas com certeza é uma maneira mais C ++ do que “manualmente”, certificando-se de excluir uma matriz.

Agora, com C ++ 11, há também std :: array que modela uma matriz de tamanho constante (vetor vs que é capaz de crescer). Há também std :: unique_ptr que gerencia uma matriz alocada dinamicamente (que pode ser combinada com a boot como respondida em outras respostas a essa pergunta). Qualquer um desses é um caminho mais C ++ do que manipular manualmente o ponteiro para a matriz, IMHO.

std::fill é um caminho. Leva dois iteradores e um valor para preencher a região. Isso, ou o loop for, (suponho) seria o caminho mais C ++.

Para definir uma matriz de tipos inteiros primitivos como 0, especificamente, memset é bom, embora possa levantar as sobrancelhas. Considere também calloc , embora seja um pouco inconveniente para usar a partir de C ++ por causa do casting.

De minha parte, eu praticamente sempre uso um loop.

(Eu não gosto de adivinhar as intenções das pessoas, mas é verdade que std::vector é, todas as coisas sendo iguais, preferível ao uso de new[] .)

você sempre pode usar memset:

 int myArray[10]; memset( myArray, 0, 10 * sizeof( int )); 

Normalmente, para listas dinâmicas de itens, você usa um std::vector .

Geralmente eu uso memset ou um loop para alocação dinâmica de memory bruta, dependendo de como variável eu prevejo que a área de código seja no futuro.