Buscar..


Sintaxis

  • : :( opt ) nuevo ( expresión-lista ) ( opt ) new-type-id new-initializer ( opt )
  • : :( opt ) nuevo ( expresión-lista ) ( opt ) ( type-id ) new-initializer ( opt )
  • : :( opt) borrar fundido expresión
  • : :( Opción ) borrar [] expresión-cast
  • std :: unique_ptr < type-id > var_name (nuevo type-id ( opt )); // C ++ 11
  • std :: shared_ptr < type-id > var_name (nuevo type-id ( opt )); // C ++ 11
  • std :: shared_ptr < type-id > var_name = std :: make_shared < type-id > ( opt ); // C ++ 11
  • std :: unique_ptr < type-id > var_name = std :: make_unique < type-id > ( opt ); // C ++ 14

Observaciones

Un líder :: obliga a buscar el operador nuevo o de borrado en el ámbito global, anulando cualquier operador nuevo o de borrado específico de clase sobrecargado.

Los argumentos opcionales que siguen a la new palabra clave se usan generalmente para llamar ubicación nueva , pero también se pueden usar para pasar información adicional al asignador, como una etiqueta que solicita que la memoria se asigne de un grupo elegido.

El tipo asignado generalmente se especifica explícitamente, por ejemplo, new Foo , pero también se puede escribir como auto (desde C ++ 11) o decltype(auto) (desde C ++ 14) para deducirlo del inicializador.

La inicialización del objeto asignado ocurre de acuerdo con las mismas reglas que la inicialización de las variables locales. En particular, el objeto se inicializará por defecto si se omite el inicializador, y cuando se asigna dinámicamente un tipo escalar o una matriz de tipo escalar, no hay garantía de que la memoria se pondrá a cero.

Un objeto de matriz creado por una nueva expresión se debe destruir utilizando delete[] , independientemente de si la nueva expresión se escribió con [] o no. Por ejemplo:

using IA = int[4];
int* pIA = new IA;
delete[] pIA;  // right
// delete pIA;  // wrong

Apilar

La pila es una pequeña región de memoria en la que se colocan valores temporales durante la ejecución. La asignación de datos en la pila es muy rápida en comparación con la asignación de almacenamiento dinámico, ya que toda la memoria ya se ha asignado para este propósito.

int main() {
    int a = 0; //Stored on the stack
    return a;
}

La pila se llama así porque las cadenas de llamadas a funciones tendrán su memoria temporal "apilada" una encima de la otra, cada una utilizando una pequeña sección separada de la memoria.

float bar() {
    //f will be placed on the stack after anything else
    float f = 2;
    return f;
}

double foo() {
    //d will be placed just after anything within main()
    double d = bar();
    return d;
}

int main() {
    //The stack has no user variables stored in it until foo() is called
    return (int)foo();
}

Los datos almacenados en la pila solo son válidos mientras el alcance que asignó la variable aún esté activo.

int* pA = nullptr;

void foo() {
    int b = *pA;
    pA = &b;
}

int main() {
    int a = 5;
    pA = &a;
    foo();
    //Undefined behavior, the value pointed to by pA is no longer in scope
    a = *pA;
}

Almacenamiento gratuito (Heap, asignación dinámica ...)

El término 'montón' es un término de computación general que significa un área de la memoria desde la cual se pueden asignar y desasignar partes independientemente de la memoria proporcionada por la pila .

En C++ el Estándar se refiere a esta área como la Tienda libre, que se considera un término más preciso.

Las áreas de memoria asignadas desde Free Store pueden vivir más tiempo que el alcance original en el que se asignó. Los datos demasiado grandes para ser almacenados en la pila también pueden asignarse desde Free Store .

La memoria sin formato se puede asignar y desasignar mediante las palabras clave new y delete .

float *foo = nullptr;
{
    *foo = new float; // Allocates memory for a float
    float bar;              // Stack allocated 
} // End lifetime of bar, while foo still alive

delete foo;          // Deletes the memory for the float at pF, invalidating the pointer
foo = nullptr;       // Setting the pointer to nullptr after delete is often considered good practice

También es posible asignar matrices de tamaño fijo con nuevas y eliminar , con una sintaxis ligeramente diferente. La asignación de arrays no es compatible con la asignación sin arrays, y mezclar los dos llevará a la corrupción del montón. La asignación de una matriz también asigna memoria para rastrear el tamaño de la matriz para su posterior eliminación de una manera definida por la implementación.

// Allocates memory for an array of 256 ints
int *foo = new int[256];
// Deletes an array of 256 ints at foo
delete[] foo;

Al usar new y delete en lugar de malloc y free , el constructor y el destructor se ejecutarán (similar a los objetos basados ​​en la pila). Esta es la razón por la cual nuevo y eliminar son preferidos a malloc y gratis .

struct ComplexType {
    int a = 0;

    ComplexType() { std::cout << "Ctor" << std::endl; }
    ~ComplexType() { std::cout << "Dtor" << std::endl; }
};

// Allocates memory for a ComplexType, and calls its constructor
ComplexType *foo = new ComplexType();
//Calls the destructor for ComplexType() and deletes memory for a Complextype at pC
delete foo;
C ++ 11

A partir de C ++ 11, se recomienda el uso de punteros inteligentes para indicar la propiedad.

C ++ 14

C ++ 14 agregó std::make_unique a la STL, cambiando la recomendación para favorecer std::make_unique o std::make_shared lugar de usar desnudo nuevo y eliminar .

Colocación nueva

Hay situaciones en las que no queremos confiar en Free Store para asignar memoria y queremos usar asignaciones de memoria personalizadas utilizando new .

Para estas situaciones, podemos usar Placement New , donde podemos decirle al operador 'nuevo' que asigne memoria desde una ubicación de memoria asignada

Por ejemplo

int a4byteInteger;

char *a4byteChar = new (&a4byteInteger) char[4];

En este ejemplo, la memoria apuntada por a4byteChar es de 4 bytes asignados a 'pila' a través de la variable entera a4byteInteger .

El beneficio de este tipo de asignación de memoria es el hecho de que los programadores controlan la asignación. En el ejemplo anterior, dado que a4byteInteger está asignado en la pila, no necesitamos hacer una llamada explícita para 'eliminar a4byteChar`.

El mismo comportamiento se puede lograr para la memoria asignada dinámica también. Por ejemplo

int *a8byteDynamicInteger = new int[2];

char *a8byteChar = new (a8byteDynamicInteger) char[8];

En este caso, el puntero de memoria de a8byteChar se a8byteChar a la memoria dinámica asignada por a8byteDynamicInteger . En este caso, sin embargo, debemos llamar explícitamente a delete a8byteDynamicInteger para liberar la memoria

Otro ejemplo para la clase de C ++

struct ComplexType {
    int a;

    ComplexType() : a(0) {}
    ~ComplexType() {}
};

int main() {
    char* dynArray = new char[256];

    //Calls ComplexType's constructor to initialize memory as a ComplexType
    new((void*)dynArray) ComplexType();

    //Clean up memory once we're done
    reinterpret_cast<ComplexType*>(dynArray)->~ComplexType();
    delete[] dynArray;

    //Stack memory can also be used with placement new
    alignas(ComplexType) char localArray[256]; //alignas() available since C++11

    new((void*)localArray) ComplexType();

    //Only need to call the destructor for stack memory
    reinterpret_cast<ComplexType*>(localArray)->~ComplexType();

    return 0;
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow