Tal vez solo estoy confundiendo un poco las cosas ... Pero considere este fragmento de código C ++:

#include <iostream>
#include <list>
using namespace std;

void printArray(int *arr, int n)
{
    for(int i=0; i<n; ++i)
    cout << arr[i] << " ";

    cout << endl;
}

int main()
{
    list<int*> arrays;
    int times=20, v[9]={1,2,3,4,5,6,7,8,0};

    arrays.push_back(v);

    while(times--)
    {
        int *cur = arrays.front();
        arrays.pop_front();

        printArray(cur, 9);

        int ta[9], tb[9];
        for(int i=0; i<9; ++i)
        {   
            ta[i] = *(cur+i)+1;
            tb[i] = *(cur+i)-1;
        }

        arrays.push_back(&ta[0]);
        arrays.push_back(&tb[0]);
    }

    return 0;
}

Como puede ver, el objetivo es, comenzando con una matriz predeterminada {1,2,3,4,5,6,7,8,0}, almacenar (en veces iteraciones) 2 variantes de esta matriz en una lista de punteros int.

Entonces, en la primera iteración las 2 matrices {2,3,4,5,6,7,8,9,1} y {0,2,3, , 5,6,7, -1} deben almacenarse en la lista y, por lo tanto, los primeros 3 printArray deben ser:

1 2 3 4 5 6 7 8 0
2 3 4 5 6 7 8 9 1
0 1 2 3 4 5 6 7 -1

Ahora, lo que está sucediendo es que los primeros 3 printArray son:

1 2 3 4 5 6 7 8 0
2 3 4 5 6 7 8 9 1
2 3 4 5 6 7 8 9 1

Ya imprimí ta y tb en cada iteración y sé que lo que realmente se imprime es 1) matriz predeterminada, 2) primera ta, 3) tb de la primera ta. Pero realmente no sé cuál es la razón de este comportamiento, quiero decir, ¿no son ta y tb nuevas matrices (independientes de las anteriores) en cada iteración? Si este es el caso, mi para es simplemente asignar valores para las nuevas posiciones de las matrices, entonces, ¿por qué están en conflicto entre sí?

-1
yat0 4 dic. 2016 a las 20:17
1
Tenga en cuenta que la memoria de las matrices ta y tb no es administrada por el vector std. Supongo que en las sucesivas iteraciones, las matrices podrían desasignarse y el comportamiento no está definido. Intente asignarlos fuera del bucle while
 – 
quimnuss
4 dic. 2016 a las 20:23
Además, no tiene tres matrices de punteros int, tiene tres punteros a matrices int respectivas.
 – 
quimnuss
4 dic. 2016 a las 20:26
Tiene sentido si esa es la razón. Y sí, funciona si previamente asigno la cantidad de matrices necesarias fuera del ciclo while o simplemente si solo int *ta = new int[9] ... en cada iteración, que es básicamente lo mismo. Supongo que, dado que ta y tb son variables locales del bucle while, solo tendrán validez hasta el final del alcance, y ese es el final de la iteración en sí ... ¿Está de acuerdo? @quimnuss
 – 
yat0
4 dic. 2016 a las 20:39
Sí, eso es lo que está pasando.
 – 
quimnuss
4 dic. 2016 a las 20:47
Gracias por tu ayuda :) @quimnuss
 – 
yat0
4 dic. 2016 a las 20:48

1 respuesta

La mejor respuesta

En realidad, el problema es bastante simple.

Como @quimnuss declaró en los comentarios, ta y tb se desasignaron en algún momento y, por lo tanto, los punteros guardados en la lista apuntarían a algo completamente diferente de las matrices que estaban desasignado, que conduce a un comportamiento indefinido del programa.

Esta declaración tiene mucho sentido ya que ta y tb son variables locales del ciclo while y, por lo tanto, su validez se agotará en cada iteración completada.

Podemos solucionar este problema asignando memoria dinámicamente en cada iteración, como:

int *ta = new int[9];
int *tb = new int[9];

Esto no ocurrirá pérdida de información al final de cada iteración, ya que el alcance de estas matrices ya no es local para el ciclo while.

Código final:

#include <iostream>
#include <list>
using namespace std;

void printArray(int *arr, int n)
{
    for(int i=0; i<n; ++i)
    cout << arr[i] << " ";

    cout << endl;
}


int main()
{
    list<int*> arrays;
    int times=20;    

    int *v = new int[9];
    for(int i=0; i<8; ++i)
        v[i] = i+1;
    v[8] = 0;

    arrays.push_back(v);

    while(times--)
    {
        int *cur = arrays.front();
        arrays.pop_front();

        printArray(cur, 9);

        int *ta = new int[9];
        int *tb = new int[9];

        for(int i=0; i<9; ++i)
        {   
            ta[i] = *(cur+i)+1;
            tb[i] = *(cur+i)-1;
        }

        arrays.push_back(ta);
        arrays.push_back(tb);

        delete[] cur;
    }

    while(!arrays.empty())
    {
        int *p = arrays.front();
        arrays.pop_front();
        delete[] p;
    }

    return 0;
}
0
yat0 6 dic. 2016 a las 19:31
2
Estás jugando con fuego aquí. El primer elemento de arrays es v, que se asigna en la pila. El resto se asigna dinámicamente, por lo que debe ser delete d. ¿Estás seguro de que no puedes usar std :: vector o std :: array ? Facilitaría mucho la gestión de la memoria
 – 
Joseph Ireland
4 dic. 2016 a las 21:20
Sí, y lo hice ... Esta era solo una forma en que un amigo mío estaba tratando de hacer, en el contexto de un problema, y ​​me intrigó y solo pregunté por qué no estaba funcionando. Actualizaré el código, eliminaré la memoria justo después de usarla. @JosephIrlanda
 – 
yat0
4 dic. 2016 a las 22:00
Entonces, esto es correcto aunque es muy, muy feo. Estoy de acuerdo con Joseph en que estás jugando con fuego. No obstante, tiene, sin embargo, una gran pérdida de memoria ya que crea times*2+1 vectores asignados al montón y solo elimina times. Insisto, mueva la asignación y la eliminación fuera del ciclo, de lo contrario, está mezclando ámbitos y, aunque funcionaría porque está asignado en montón, es bastante difícil de leer. Tenga en cuenta que la asignación puede permanecer como está. Además de la pérdida de memoria que aún tienes.
 – 
quimnuss
4 dic. 2016 a las 23:58
Entiendo lo que estás diciendo y lo haré ... Pero dime, ¿cómo se supone que debo mover las asignaciones fuera del ciclo? Si voy a asignar 2 * veces + 1 matrices y almacenarlas previamente en la lista, entonces el ciclo ya no tiene sentido ya que iba a ajustarlo para hacer algo un poco extraño. ¿No podría simplemente, en al final del ciclo, iterar sobre los punteros restantes en la lista y eliminarlos? @quimnuss
 – 
yat0
5 dic. 2016 a las 02:16
Sí, ahora es correcto. Pensó que sería más limpio usar contenedores estándar en lugar de matrices. También simplificaría el código.
 – 
quimnuss
6 dic. 2016 a las 17:46