Asignación dinámica de una serie de punteros a objetos

Pregunta:

Tengo una clase llamada croba. En mi aplicación de consola tengo un menú en el que puedo elegir diferentes opciones. Después de elegir una opción, una declaración de conmutación comprueba mi entrada y ejecuta el bloque que elegí.

En uno de los casos quiero que el programa aloque dinámicamente una serie de punteros a objetos de clase de un tamaño desconocido (se le pide al usuario que ingrese el tamaño de la matriz), la captura es que la entrada del usuario y la matriz deben ser alocadas en el bloque "caso", pero la matriz alocada tiene que ser accedido globalmente más adelante en el código. Declaré un puntero para oponerse globalmente así:

croba *arrayOfObjectsPtr = NULL;

Y aquí está el bloque "caso":

case 3:{
            int numberOfElements;
            int indexNumber;
            if(!arrayOfObjectsPtr){
                do{
                    cout << endl << "How many linked lists? "; cin >> numberOfElements;
                }while(numberOfElements < 1);
                croba *arrayOfObjectsPtrLocal[numberOfElements];
                for (int i = 0; i < numberOfElements; i++){
                    arrayOfObjectsPtrLocal[i] = new croba;
                }
            }else{
                cout << endl << "The array is already alocated!" << endl;
            }
            arrayOfObjectsPtr = arrayOfObjectsPtrLocal;
            break;
        }

Estoy tratando de averiguar si hay una manera de declarar un puntero a una serie de punteros a objetos de clase globalmente y luego localizarlo más tarde (porque el número de elementos no se conoce antes).

Pregunta hecha hace 3 años, 4 meses, 27 días - Por codeartisan


3 Respuestas:

  • En C++, la mejor práctica es usar std::vector, que es la clase de matriz dinámica de la biblioteca estándar. Es mucho más agradable utilizar que los arrays de estilo C. En su caso parecería así: std::vector arrayOfObjectsPtr. Tenga cuidado, porque tendrá que eliminar manualmente los punteros en el vector antes de la destrucción, así:

    for (auto& obj : arrayOfObjectsPtr)
        delete obj;
    

    Si no quieres realizar la limpieza manualmente, como arriba, usa un vector de punteros inteligentes, como std::unique_ptr.

    Si todavía desea utilizar la antigua matriz de estilo C (que no es recomendable), entonces declare de esta manera:croba** arrayOfObjectsPtr = new croba*[numberOfElements]. En cuanto a la limpieza, tendrás que hacer esto:

    for (int i = 0; i < numberOfElements; ++i)
        delete arrayOfObjectsPtr[i];
    delete[] arrayOfObjectsPtr;
    

    Respondida el Dec 18, 2020 a las 17:38 - por byteexplorer

    Votos positivos: 0 | Votos negativos: 0

  • Sí, puedes lograr lo que deseas declarando un puntero a un puntero globalmente y asignándole memoria dinámicamente en el bloque "caso". Aquí te muestro cómo puedes mejorar tu código:

    • En lugar de declarar un arreglo local de punteros a objetos dentro del bloque "caso", puedes declarar un puntero a puntero globalmente y asignarle memoria dinámicamente en el bloque "caso".
    • Al asignar memoria dinámicamente en el bloque "caso", asegúrate de liberar la memoria asignada previamente para evitar fugas de memoria.

    Aquí te dejo una versión modificada de tu código:

    cpp
    croba *arrayOfObjectsPtr = NULL;
    
    // En el bloque main o donde declares tu menú:
    int main() {
        // Resto de tu código...
    
        switch (opcion) {
            case 3:{
                int numberOfElements;
                int indexNumber;
                if(!arrayOfObjectsPtr){
                    do{
                        cout << endl << "How many linked lists? "; cin >> numberOfElements;
                    }while(numberOfElements < 1);
                    arrayOfObjectsPtr = new croba[numberOfElements];
                    for (int i = 0; i < numberOfElements; i++){
                        arrayOfObjectsPtr[i] = new croba;
                    }
                }else{
                    cout << endl << "The array is already allocated!" << endl;
                }
                break;
            }
        }
    
        // Resto de tu código...
    
        // Liberar memoria asignada dinámicamente al final del programa
        if (arrayOfObjectsPtr) {
            for (int i = 0; i < numberOfElements; i++) {
                delete arrayOfObjectsPtr[i];
            }
            delete[] arrayOfObjectsPtr;
        }
    
        return 0;
    }
    

    Al hacer estos cambios, declaras un puntero a puntero globalmente, lo asignas dinámicamente en el bloque "caso" y te aseguras de liberar la memoria asignada al final del programa. Esto te permitirá acceder a la matriz de punteros a objetos de clase globalmente en tu código. ¡Espero que esta solución te sea útil!

    Respondida el Dec 19, 2020 a las 17:36 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Claro, puedes declarar un puntero a una matriz de punteros a objetos de clase globalmente y luego asignarle espacio dinámicamente más tarde. Aquí tienes un ejemplo de cómo podrías hacerlo:

    cpp
    include 
    using namespace std;
    
    class Croba {
    public:
      Croba() { cout << "Constructor de Croba" << endl; }
      ~Croba() { cout << "Destructor de Croba" << endl; }
    };
    
    int main() {
      // Declarar un puntero a una matriz de punteros a objetos de clase globalmente
      Croba *arrayOfObjectsPtr = nullptr;
    
      // Solicitar al usuario el tamaño de la matriz
      int numberOfElements;
      cout << "Número de elementos: ";
      cin >> numberOfElements;
    
      // Asignar espacio dinámicamente para la matriz
      arrayOfObjectsPtr = new Croba[numberOfElements];
    
      // Crear objetos y asignarlos a la matriz
      for (int i = 0; i < numberOfElements; i++) {
        arrayOfObjectsPtr[i] = new Croba;
      }
    
      // Acceder a los objetos de la matriz más adelante en el código
      for (int i = 0; i < numberOfElements; i++) {
        // Hacer algo con arrayOfObjectsPtr[i]
        cout << "Accediendo al objeto " << i << endl;
      }
    
      // Liberar la memoria asignada
      for (int i = 0; i < numberOfElements; i++) {
        delete arrayOfObjectsPtr[i];
      }
      delete[] arrayOfObjectsPtr;
    
      return 0;
    }
    

    En este ejemplo, el puntero arrayOfObjectsPtr se declara globalmente y luego se le asigna espacio dinámicamente en el bloque main. Los objetos se crean y asignan a la matriz mediante un bucle for. Más adelante en el código, se puede acceder a los objetos de la matriz mediante el puntero arrayOfObjectsPtr. Por último, se libera la memoria asignada mediante otro bucle for.

    Respondida el Dec 19, 2020 a las 17:46 - por Gemini

    Votos positivos: 0 | Votos negativos: 0