¿Cómo funciona el montón en c ++

Video: Contador, acumulador e interruptor C++

los montón es un bloque amorfo de memoria que su programa en C ++ se puede acceder cuando sea necesario. Aprender acerca de por qué existe y cómo usarlo.

Así como es posible pasar un puntero a una función, es posible para una función para devolver un puntero. Una función que devuelve la dirección de una doble está declarada como sigue:

doble * fn (void) -

Sin embargo, hay que tener mucho cuidado a la hora de devolver un puntero. Para entender los peligros, debe saber algo de alcance variable.

Alcance limitado en C ++

Scapa pluvial es el intervalo en el que se define una variable. Considere el siguiente fragmento de código:

// la siguiente variable es accesible a todas las funciones // y se define como el tiempo que el programa se está ejecutando // (alcance global) int intGlobal - // la siguiente intChild variable es accesible // sólo para la función y sólo se define // siempre que C ++ es hijo de ejecutar () o una función de cuál de los niños // () llama (ámbito de la función) niño (void) {int intChild -} // la siguiente intParent variable tiene la función // matriz scopevoid (void) {int intParent = 0-infantil () - int intLater = 0-intParent = intLater-} int main (int n-argumentos, char * pargs []) {parent () -}

Este fragmento de programa se inicia con la declaración de una variable intGlobal. Esta variable existe desde el momento en que el programa comienza a ejecutar hasta que se termina. Tu dices eso intGlobal “Tiene el alcance del programa.” También dice que la variable “entra en el alcance”, incluso antes de la función principal() se llama.

La función principal() invoca inmediatamente padre(). La primera cosa que el procesador ve en padre() es la declaración de intParent. En ese punto, intParent entra en el alcance - que es, intParent se define y disponible para el resto de la función de padre().

La segunda declaración en padre() es la llamada a niño(). Una vez más, la función niño() declara una variable local, esta vez intChild. El alcance de la variable intChild se limita a la función de niño(). Técnicamente, intParent no está definida dentro del alcance de niño() porque niño() no tiene acceso a intParent- Sin embargo, la variable intParent continúa existiendo mientras niño() se está ejecutando.

Cuando niño() salidas, la variable intChild se sale del ámbito. No sólo es intChild ya no es accesible, ya no existe. (La memoria ocupada por intChild se devuelve a la piscina en general a ser utilizado para otras cosas.)

Como padre() continúa la ejecución, la variable intLater entra en el alcance de la declaración. En el punto de que padre() vuelve a principal(), ambos intParent y intLater ir fuera de alcance.

Porque intGlobal se declara a nivel mundial en este ejemplo, está disponible para las tres funciones y permanece disponible para la vida del programa.

Examinando el problema alcance en C ++

El siguiente segmento de código se compila sin error, pero no funciona (no te odio, que?):

Video: Como usar switch en C++

* doble niño (void) {double-retorno dLocalVariable &dLocalVariable-} padre (void) {double * pdLocal-pdLocal = niño () - * pdLocal = 1.0-}

El problema con esto es que la función dLocalVariable sólo se define dentro del alcance de la función de niño(). Por lo tanto, por el momento la dirección de memoria de dLocalVariable se devuelve desde niño(), se refiere a una variable que ya no existe. La memoria que dLocalVariable anteriormente ocupado probablemente está siendo usado para otra cosa.

Este error es muy común, ya que puede arrastrarse para arriba en un número de maneras. Por desgracia, este error no hace que el programa se detenga de inmediato. De hecho, el programa puede funcionar bien la mayor parte del tiempo - es decir, el programa continúa trabajando, siempre y cuando la memoria anteriormente ocupado por dLocalVariable No se vuelve a utilizar de inmediato. Tales problemas intermitentes son los más difíciles de resolver.

Proporcionar una solución utilizando el montón en C ++

El problema se originó porque el alcance de C ++ tomó de nuevo la memoria definida localmente antes de que el programador estaba listo. Lo que se necesita es un bloque de memoria controlada por el programador. Se puede asignar la memoria y poner de nuevo cuando ella quiere - no porque C ++ piensa que es una buena idea. un bloque de este tipo de memoria se llama la montón.

memoria dinámica se asigna mediante el nuevo palabra clave seguida por el tipo de objeto a asignar. los nuevo comando rompe un trozo de memoria fuera del montón lo suficientemente grande como para contener el tipo especificado de objeto y devuelve su dirección. Por ejemplo, la siguiente asigna una doble variable de fuera del montón:

* doble niño (void) {double * pdLocalVariable = new doble vuelta pdLocalVariable-}

Esta función ahora funciona correctamente. Aunque la variable pdLocalVariable sale del ámbito cuando la función de niño() devoluciones, la memoria a la que pdLocalVariable se refiere no lo hace. Una posición de memoria devuelto por nuevo no sale del alcance hasta que se devuelve de forma explícita a la pila usando la palabra clave borrar, que está diseñado específicamente para tal fin:

padre (void) {// niño () devuelve la dirección de un bloque de // memorydouble montón * = pdMyDouble niño () - // almacenar un valor allí * pdMyDouble = 1,1 - // ... // ahora devolver el memoria a la heapdelete pdMyDouble-pdMyDouble = 0 - // ...}

Aquí el puntero devuelto por niño() se utiliza para almacenar un valor doble. Después de la función ha terminado con la posición de memoria, se devuelve al montón. La función padre() establece el puntero a 0 después de la memoria de almacenamiento dinámico se ha vuelto - esto no es un requisito, pero es una idea muy buena.

Si el programador intenta erróneamente para almacenar algo en * pdMyDouble después de la borrar, el programa se bloqueará inmediatamente con un mensaje de error significativo.

Puedes usar nuevo asignar matrices del montón también, pero debe devolver una matriz mediante la borrar[] palabra clave:

int * nArray = new int [10] -nArray [0] = 0-delete [] nArray-

Técnicamente new int [10] invoca la nuevo[] operador, sino que funciona de la misma como nuevo.

Artículos Relacionados