Me topé con un cuestionario que involucraba una declaración de matriz con diferentes tamaños. Lo primero que me vino a la mente es que necesitaría usar una asignación dinámica con el newcomando, así:
while(T--) {
int N;
cin >> N;
int *array = new int[N];
// Do something with 'array'
delete[] array;
}
Sin embargo, vi que una de las soluciones permitía el siguiente caso:
while(T--) {
int N;
cin >> N;
int array[N];
// Do something with 'array'
}
Después de un poco de investigación, leí que g ++ permite esto, pero me mantuvo pensando, ¿en qué casos es necesario usar la asignación dinámica? ¿O es que el compilador traduce esto como asignación dinámica?
La función de eliminación está incluida. Sin embargo, tenga en cuenta que la pregunta aquí no se trata de pérdidas de memoria.
c++
arrays
dynamic-memory-allocation
static-memory-allocation
aprendizaje_dude
fuente
fuente

std::vectoren su lugar (std::vector<int> array(N);).new OBJdirectamente.Respuestas:
Ninguno de los fragmentos que muestra es un código C ++ idiomático y moderno.
newydelete(ynew[]ydelete[]) no están en desuso en C ++ y nunca lo estarán. Todavía son la forma de instanciar objetos asignados dinámicamente. Sin embargo, como siempre debe hacer coincidir anewcon adelete(y anew[]con adelete[]), es mejor guardarlos dentro de las clases (de la biblioteca) que garanticen esto. Consulte ¿Por qué los programadores de C ++ deberían minimizar el uso de 'nuevo'? .Su primer fragmento utiliza un "desnudo"
new[]y luego nuncadelete[]es la matriz creada. Eso es un problema.std::vectorhace todo lo que necesitas aquí bien. Utilizará alguna forma denewdetrás de escena (no me sumergiré en los detalles de implementación), pero por lo que debe preocuparse, es una matriz dinámica pero mejor y más segura.Su segundo fragmento utiliza "matrices de longitud variable" (VLA), una característica de C que algunos compiladores también permiten en C ++ como una extensión. A diferencia
new, los VLA se asignan esencialmente en la pila (un recurso muy limitado). Pero lo más importante, no son una característica estándar de C ++ y deben evitarse porque no son portátiles. Ciertamente no reemplazan la asignación dinámica (es decir, el montón).fuente
Qt, ya que todas sus clases base tienen recolectores de basura, por lo que solo debe usarlonewy olvidarse de él la mayor parte del tiempo. Para los elementos de la GUI, cuando el widget primario está cerrado, los secundarios quedan fuera del alcance y se recolectan basura automáticamente.newtiene una coincidenciadelete; es solo que lasdeletes las realiza el widget principal en lugar del mismo bloque de código que lasnews.Bueno, para empezar,
new/deleteno están siendo obsoleta.Sin embargo, en su caso específico, no son la única solución. Lo que elija depende de lo que se ocultó en su comentario de "hacer algo con la matriz".
Su segundo ejemplo utiliza una extensión VLA no estándar que intenta ajustar la matriz en la pila. Esto tiene ciertas limitaciones, a saber, el tamaño limitado y la imposibilidad de usar esta memoria después de que la matriz se salga del alcance. No puede moverlo, "desaparecerá" después de que la pila se desenrolle.
Entonces, si su único objetivo es hacer un cálculo local y luego descartar los datos, en realidad podría funcionar bien. Sin embargo, un enfoque más sólido sería asignar la memoria dinámicamente, preferiblemente con
std::vector. De esa manera, obtienes la capacidad de crear espacio para exactamente tantos elementos como necesites basándose en un valor de tiempo de ejecución (que es lo que vamos a hacer todo el tiempo), pero también se limpiará muy bien y podrás moverlo de este alcance si desea mantener la memoria en uso para más adelante.Dando vueltas de nuevo al principio,
vectorserá probablemente utilizarnewunas pocas capas más profundas, pero no debe preocuparse por eso, como la interfaz que presenta es muy superior. En ese sentido, usarnewydeletepuede considerarse desalentado.fuente
newydelete, sino usar punteros inteligentes comostd::unique_pointer.std::unique_ptrstd::unique_ptrllamadas destructor predeterminadasdeleteodelete[], lo que significa que el objeto de propiedad debe haber sido asignado pornewo denew[]todos modos, qué llamadas han estado ocultasstd::make_uniquedesde C ++ 14.Su segundo ejemplo utiliza matrices de longitud variable (VLA), que en realidad son una función C99 (¡ no C ++!), Pero que sin embargo es compatible con g ++ .
Ver también esta respuesta .
Tenga en cuenta que las matrices de longitud variable son diferentes de
new/deletey no las "desprecian" de ninguna manera.También tenga en cuenta que los VLA no son ISO C ++.
fuente
Modern C ++ proporciona formas más fáciles de trabajar con asignaciones dinámicas. Los punteros inteligentes pueden encargarse de la limpieza después de las excepciones (que pueden ocurrir en cualquier lugar si se permite) y los retornos anticipados, tan pronto como las estructuras de datos referenciadas salgan del alcance, por lo que puede tener sentido usar estas en su lugar:
Desde C ++ 14 también puedes escribir
esto se ve aún mejor y evitaría la pérdida de memoria si falla la asignación. Desde C ++ 20 deberías poder hacer tanto como
esto para mí todavía no se compila al momento de escribir con gcc 7.4.0. En estos dos ejemplos también usamos en
autolugar de la declaración de tipo a la izquierda. En todos los casos, use la matriz como de costumbre:La pérdida de memoria
newy los bloqueos por duplicacióndeletees algo que C ++ ha sido criticado durante muchos años, siendo el "punto central" de la argumentación para cambiar a otros lenguajes. Quizás sea mejor evitarlo.fuente
unique/shared_ptrconstructores a favormake_unique/shared, no solo no tiene que escribir el tipo construido dos veces (usandoauto) sino que no corre el riesgo de perder memoria o recursos si la construcción falla a la mitad (si está usando un tipo que puede fallar)make_shared<int[]>mucho, cuando casi siempre quieresvector<int>, pero es bueno saberlo.unique_ptrconstructor no es arrojar, por loTque no tienen constructores, por lo que no hay riesgo de fugasunique_ptr(new int[size])yshared_ptrtiene lo siguiente: "Si se produce una excepción, se llama a p cuando T no es un tipo de matriz, eliminar [ ] p de otro modo ", por lo que tiene el mismo efecto -. el riesgo es paraunique/shared_ptr(new MyPossiblyAllocatingType[size]).new y delete no se están desaprobando.
Los objetos creados por el nuevo operador se pueden pasar por referencia. Los objetos se pueden eliminar con eliminar.
nuevo y eliminar son los aspectos fundamentales del lenguaje. La persistencia de un objeto se puede administrar usando new y delete. Definitivamente, estos no serán desaprobados.
La declaración - int array [N] es una forma de definir una matriz. La matriz se puede usar dentro del alcance del bloque de código adjunto. No se puede pasar como cómo se pasa un objeto a otra función.
fuente
El primer ejemplo necesita un
delete[]al final, o tendrá una pérdida de memoria.El segundo ejemplo usa una longitud de matriz variable que no es compatible con C ++; que sólo permite constante-expresión para longitud de la matriz .
En este caso es útil usarlo
std::vector<>como solución; que envuelve todas las acciones que puede realizar en una matriz en una clase de plantilla.fuente
La sintaxis se parece a C ++, pero el idioma es similar al antiguo Algol60. Era común tener bloques de código como este:
El ejemplo podría escribirse como:
A veces extraño esto en los idiomas actuales;)
fuente