Es más sutil de lo que sugieren las otras respuestas. No hay una división absoluta entre los datos en la pila y los datos en el montón en función de cómo lo declare. Por ejemplo:
std::vector<int> v(10);
En el cuerpo de una función, que declara una vector
(matriz dinámica) de diez enteros en la pila. Pero el almacenamiento gestionado por el vector
no está en la pila.
Ah, pero (las otras respuestas sugieren) la vida útil de ese almacenamiento está limitada por la vida útil del vector
mismo, que aquí está basada en la pila, por lo que no importa cómo se implemente; solo podemos tratarlo como un objeto basado en la pila con valor semántico.
No tan. Supongamos que la función era:
void GetSomeNumbers(std::vector<int> &result)
{
std::vector<int> v(10);
// fill v with numbers
result.swap(v);
}
Por lo tanto, cualquier cosa que tenga una swap
función (y cualquier tipo de valor complejo debería tener una) puede servir como una especie de referencia modificable a algunos datos de almacenamiento dinámico, en un sistema que garantiza un único propietario de esos datos.
Por lo tanto, el enfoque moderno de C ++ es nunca almacenar la dirección de los datos del montón en variables de puntero locales desnudas. Todas las asignaciones de montón deben estar ocultas dentro de las clases.
Si hace eso, puede pensar en todas las variables en su programa como si fueran tipos de valores simples, y olvidarse del montón por completo (excepto al escribir una nueva clase de contenedor de valor para algunos datos de montón, lo que debería ser inusual) .
Simplemente tiene que retener un conocimiento especial para ayudarlo a optimizar: cuando sea posible, en lugar de asignar una variable a otra como esta:
a = b;
intercambiarlos así:
a.swap(b);
porque es mucho más rápido y no arroja excepciones. El único requisito es que no necesita b
continuar manteniendo el mismo valor (en su a
lugar, obtendrá el valor, que se tiraría a la basura a = b
).
La desventaja es que este enfoque lo obliga a devolver valores de funciones a través de parámetros de salida en lugar del valor de retorno real. Pero lo están arreglando en C ++ 0x con referencias rvalue .
En las situaciones más complicadas de todas, llevaría esta idea al extremo general y usaría una clase de puntero inteligente como la shared_ptr
que ya está en tr1. (Aunque diría que si parece que lo necesita, posiblemente se haya mudado fuera del punto ideal de aplicabilidad de Standard C ++).