Compartilhar via


new operador (C++)

Tenta alocar e inicializar um objeto ou matriz de objetos de um tipo especificado ou de espaço reservado e retorna um ponteiro não zero e tipado adequadamente para o objeto (ou para o objeto inicial da matriz).

Sintaxe

new-expression:
:: optarnewnew-placementoptarnew-type-idnew-initializeroptar
:: optarnewnew-placementoptar(type-id)new-initializeroptar

new-placement:
( expression-list )

new-type-id:
type-specifier-seq new-declarator optar

new-declarator:
ptr-operator new-declarator optar
noptr-new-declarator

noptr-new-declarator:
[ expression ] attribute-specifier-seq optar
noptr-new-declarator [ constant-expression ] attribute-specifier-seq optar

new-initializer:
( expression-list optar)
braced-init-list

Observações

Se não tiver êxito, new retornará zero ou gerará uma exceção. Para obter mais informações, consulte The new and delete Operators. Você pode alterar esse comportamento padrão escrevendo uma rotina personalizada de tratamento de exceções e chamando a _set_new_handler função de biblioteca em tempo de execução com o nome da função como seu argumento.

Para obter informações sobre como criar um objeto no heap gerenciado em C++/CLI e C++/CX, consulte gcnew.

Observação

As Extensões de Componente do Microsoft C++ (C++/CX) dão suporte à new palavra-chave para adicionar entradas de slot vtable. Para obter mais informações, consulte new (novo slot na vtable)

Quando new é usado para alocar memória para um objeto de classe C++, o construtor do objeto é chamado depois que a memória é alocada.

Use o delete operador para desalocar a memória alocada pelo new operador. Use o delete[] operador para excluir uma matriz alocada pelo new operador.

O exemplo a seguir aloca e libera uma matriz bidimensional de caracteres de tamanho dim em 10. Ao alocar uma matriz multidimensional, todas as dimensões, exceto a primeira, devem ser expressões constantes que são avaliadas como valores positivos. A dimensão da matriz mais à esquerda pode ser qualquer expressão que seja avaliada como um valor positivo. Ao alocar uma matriz usando o new operador, a primeira dimensão pode ser zero; o new operador retorna um ponteiro exclusivo.

char (*pchar)[10] = new char[dim][10];
delete [] pchar;

Não type-id é possível conter constdeclarações volatilede classe ou declarações de enumeração. A expressão a seguir é mal formada:

volatile char *vch = new volatile char[20];

O new operador não aloca tipos de referência porque eles não são objetos.

O new operador não pode ser usado para alocar uma função, mas pode ser usado para alocar ponteiros para funções. O exemplo a seguir aloca e libera uma matriz de sete ponteiros para funções que retornam inteiros.

int (**p) () = new (int (*[7]) ());
delete p;

Se você usar o operador new sem argumentos extras e compilar com a opção /GX, /EHaou /EHs opção, o compilador gerará código para chamar o operador delete se o construtor gerar uma exceção.

A lista a seguir descreve os elementos gramaticais de new:

new-placement
Fornece uma maneira de passar argumentos extras se você sobrecarregar new.

type-id
Especifica o tipo a ser alocado; pode ser um tipo interno ou definido pelo usuário. Se a especificação de tipo for complicada, ela poderá ser cercada por parênteses para forçar a ordem da associação. O tipo pode ser um espaço reservado (auto) cujo tipo é determinado pelo compilador.

new-initializer
Fornece um valor para o objeto inicializado. Inicializadores não podem ser especificados para matrizes. O new operador criará matrizes de objetos somente se a classe tiver um construtor padrão.

noptr-new-declarator
Especifica os limites de uma matriz. Ao alocar uma matriz multidimensional, todas as dimensões, exceto a primeira, devem ser expressões constantes que são avaliadas como valores positivos conversíveis para std::size_t. A dimensão da matriz mais à esquerda pode ser qualquer expressão que seja avaliada como um valor positivo. Aplica-se attribute-specifier-seq ao tipo de matriz associado.

Exemplo: Alocar e liberar uma matriz de caracteres

O exemplo de código a seguir aloca uma matriz de caracteres e um objeto de classe CName e os libera.

// expre_new_Operator.cpp
// compile with: /EHsc
#include <string.h>

class CName {
public:
   enum {
      sizeOfBuffer = 256
   };

   char m_szFirst[sizeOfBuffer];
   char m_szLast[sizeOfBuffer];

public:
   void SetName(char* pszFirst, char* pszLast) {
     strcpy_s(m_szFirst, sizeOfBuffer, pszFirst);
     strcpy_s(m_szLast, sizeOfBuffer, pszLast);
   }

};

int main() {
   // Allocate memory for the array
   char* pCharArray = new char[CName::sizeOfBuffer];
   strcpy_s(pCharArray, CName::sizeOfBuffer, "Array of characters");

   // Deallocate memory for the array
   delete [] pCharArray;
   pCharArray = NULL;

   // Allocate memory for the object
   CName* pName = new CName;
   pName->SetName("Firstname", "Lastname");

   // Deallocate memory for the object
   delete pName;
   pName = NULL;
}

Exemplo: new operador

Se você usar o formulário de posicionamento do new operador (o formulário com mais argumentos do que o tamanho), o compilador não oferecerá suporte a delete um formulário de posicionamento do operador se o construtor gerar uma exceção. Por exemplo:

// expre_new_Operator2.cpp
// C2660 expected
class A {
public:
   A(int) { throw "Fail!"; }
};
void F(void) {
   try {
      // heap memory pointed to by pa1 will be deallocated
      // by calling ::operator delete(void*).
      A* pa1 = new A(10);
   } catch (...) {
   }
   try {
      // This will call ::operator new(size_t, char*, int).
      // When A::A(int) does a throw, we should call
      // ::operator delete(void*, char*, int) to deallocate
      // the memory pointed to by pa2.  Since
      // ::operator delete(void*, char*, int) has not been implemented,
      // memory will be leaked when the deallocation can't occur.

      A* pa2 = new(__FILE__, __LINE__) A(20);
   } catch (...) {
   }
}

int main() {
   A a;
}

Inicializando objetos alocados com new

Um campo opcional new-initializer é incluído na gramática do new operador. Esse campo permite que novos objetos sejam inicializados com construtores definidos pelo usuário. Para obter mais informações sobre como a inicialização é feita, consulte Initializers. O exemplo a seguir ilustra como usar uma expressão de inicialização com o new operador:

// expre_Initializing_Objects_Allocated_with_new.cpp
class Acct
{
public:
    // Define default constructor and a constructor that accepts
    //  an initial balance.
    Acct() { balance = 0.0; }
    Acct( double init_balance ) { balance = init_balance; }
private:
    double balance;
};

int main()
{
    Acct *CheckingAcct = new Acct;
    Acct *SavingsAcct = new Acct ( 34.98 );
    double *HowMuch = new double { 43.0 };
    // ...
}

Neste exemplo, o objeto CheckingAcct é alocado usando o new operador, mas nenhuma inicialização padrão é especificada. Portanto, o construtor padrão da classe Acct()é chamado. Em seguida, o objeto SavingsAcct é alocado da mesma maneira, exceto que ele é explicitamente inicializado para 34,98. Como 34.98 é do tipo double, o construtor que usa um argumento desse tipo é chamado para lidar com a inicialização. Por fim, o tipo HowMuch que não é de classe é inicializado como 43.0.

Se um objeto for de um tipo de classe e essa classe tiver construtores (como no exemplo anterior), o objeto poderá ser inicializado pelo new operador somente se uma dessas condições for atendida:

  • Os argumentos fornecidos no inicializador correspondem aos argumentos de um construtor.

  • A classe tem um construtor padrão (um construtor que pode ser chamado sem argumentos).

A inicialização explícita por elemento não pode ser feita ao alocar matrizes usando o new operador; somente o construtor padrão, se presente, é chamado. Para obter mais informações, consulte Argumentos padrão.

Se a alocação de memória falhar (operator new retornar um valor de 0), nenhuma inicialização será feita. Esse comportamento protege contra tentativas de inicializar dados que não existem.

Assim como acontece com as chamadas de função, a ordem na qual as expressões inicializadas são avaliadas não é definida. Além disso, você não deve contar com essas expressões sendo avaliadas completamente antes que a alocação de memória ocorra. Se a alocação de memória falhar e o new operador retornar zero, algumas expressões no inicializador poderão não ser avaliadas completamente.

Tempo de vida de objetos alocados com new

Os objetos alocados com o new operador não são destruídos quando o escopo no qual eles são definidos é encerrado. Como o new operador retorna um ponteiro para os objetos alocados, o programa deve definir um ponteiro com escopo adequado para acessar e excluir esses objetos. Por exemplo:

// expre_Lifetime_of_Objects_Allocated_with_new.cpp
// C2541 expected
int main()
{
    // Use new operator to allocate an array of 20 characters.
    char *AnArray = new char[20];

    for( int i = 0; i < 20; ++i )
    {
        // On the first iteration of the loop, allocate
        //  another array of 20 characters.
        if( i == 0 )
        {
            char *AnotherArray = new char[20];
        }
    }

    delete [] AnotherArray; // Error: pointer out of scope.
    delete [] AnArray;      // OK: pointer still in scope.
}

Depois que o ponteiro AnotherArray sair do escopo no exemplo, o objeto não poderá mais ser excluído.

Como new funciona

A new-expression (expressão que contém o new operador) faz três coisas:

  • Localiza e reserva o armazenamento para o objeto ou objetos a serem alocados. Quando esse estágio é concluído, a quantidade correta de armazenamento é alocada, mas ainda não é um objeto.

  • Inicializa os objetos. Após a conclusão da inicialização, há informações suficientes para que o armazenamento alocado seja um objeto.

  • Retorna um ponteiro para o(s) objeto(s) de um tipo de ponteiro derivado de new-type-id ou type-id. O programa usa esse ponteiro para acessar o objeto recém-alocado.

O new operador invoca a função operator new. Para matrizes de qualquer tipo e para objetos que não classsão, structou union tipos, uma função global, ::operator newé chamado para alocar armazenamento. Objetos de tipo de classe podem definir sua própria operator new função de membro estático por classe.

Quando o compilador encontra o new operador para alocar um objeto do tipoT, ele emite uma chamada para T::operator new( sizeof(T) ) ou, se nenhum usuário definido operator new for definido. ::operator new( sizeof(T) ) É como o new operador pode alocar a quantidade correta de memória para o objeto.

Observação

O argumento a ser operator new do tipo std::size_t. Esse tipo é definido em <direct.h>, <malloc.h>, <memory.h>, <search.h>, <stddef.h>, <stdio.h>, <stdlib.h>, <string.h> e <time.h>.

Uma opção na gramática permite a especificação ( new-placement consulte a Gramática para new Operador). O new-placement parâmetro pode ser usado apenas para implementações definidas pelo usuário; operator newele permite que informações extras sejam passadas para operator new. Uma expressão com um new-placement campo como T *TObject = new ( 0x0040 ) T; é traduzida para se a T *TObject = T::operator new( sizeof( T ), 0x0040 ); classe T tiver membro operator new, caso contrário, para T *TObject = ::operator new( sizeof( T ), 0x0040 );.

A intenção original do new-placement campo era permitir que objetos dependentes de hardware fossem alocados em endereços especificados pelo usuário.

Observação

Embora o exemplo anterior mostre apenas um argumento no new-placement campo, não há nenhuma restrição sobre quantos argumentos extras podem ser passados para operator new essa maneira.

Mesmo quando operator new tiver sido definido para um tipo Tde classe, você pode usar o operador new global explicitamente, como neste exemplo:

T *TObject = ::new TObject;

O operador de resolução de escopo (::) força o uso do operador global new .

Consulte também

Expressões com operadores unários
Palavras-chave
new e delete operadores