C++: vector<string *> e delete[]: errore

di il
4 risposte

C++: vector<string *> e delete[]: errore

Buongiorno a tutti

sono nuovo nel forum.
Sto imparando per puro divertimento C++ da solo da pochi giorni (vengo da Java), e mi sto scontrando con i puntatori
Il mio problema: voglio stampare a video una tabella di persone (nome, cognome, indirizzo, ecc.).
La classe che deve raccogliere i dati e passarli alla tabella, ha un ciclo del tipo:
for (int i=0; i<s; i++) {
    Person *p = pVector->at(i);
    string *str = new string[7];

    str[0] = p->getFirst();
    str[1] = p->getName();
    str[2] = p->getNumber();
    str[3] = p->getMail();
    str[4] = p->getStreet();
    str[5] = p->getPlz();
    str[6] = p->getCity();

    pTable->addRow(str);
  }
dove addRow è così definito:
void Table::addRow(string *str) {
  vct.push_back(str);
}
e vct è un vettore:
std::vector <std::string *> vct;
Il tutto funziona, ma ho visto che mi rimangono memory leaks. Allora, nel distruttore della classe Table ho scritto:

for (int i=0; i<vct.size(); i++) {
delete [] vct[i];
}
Il tutto compila, ma quando il distruttore viene chiamato, ottengo un errore:
Speicherzugriffsfehler (Speicherabzug geschrieben) credo che sia segmentation fault in inglese.
Il mio ragionamento: se nel vettore ho dei puntatori ad array di stringhe, anche se scrivere
string *str = new string[7];
in un loop non è bello, prendendo gli elementi del vettore
e passandoli al delete[] dovrebbero essere cancellati.
La mia domanda: dove sbaglio (concettualmente)?

Grazie mille e un salutone a tutto il forum

Eugenio

4 Risposte

  • Re: C++: vector<string *> e delete[]: errore

    In C++ non c'è bisogno dei puntatori se non si è costretti ad usarli.
    Se tu devi creare un vettore di 7 stringhe crei uno tale non creare un array di 7 puntatori ovvero
    std::vector<std::string> v;
    v.reserve(7);
    v.push_back(p->getFirst());
    v.push_back(p->getName());
    v.push_back(p->getNumber());
    v.push_back(p->getMail());
    v.push_back(p->getStreet());
    v.push_back(p->getPlz());
    v.push_back(p->getCity());
    
    pTable->addRow(v);
    dove addRow sarà definito come
    addrow(const std::vector & v)
    {
        vct = v;
    }
    
    dove vct sarà definito
    std::vector <std::string> vct;
    Se il tuo compilatore soppurta i move semantics addRow potrà essere definito come
    addrow(const std::vector && v)
    {
        vct = v;
    }
    Alla fine non avrai memory leaks.
  • Re: C++: vector<string *> e delete[]: errore

    Grazie mille!
    Ora provo a vedere come funziona. Per favore, potresti però aiutarmi a capire?
    Primo:
    In C++ non c'è bisogno dei puntatori se non si è costretti ad usarli.
    Quando sono davvero costretto? Io avevo l'impressione (guardando diversi esempi) che praticamente tutto si facesse con i puntatori...
    Secondo: puoi comunque spiegarmi perché il mio primo tentativo non libera memoria? Intendo, se nel vettore sono memorizzati indirizzi e io li passo ad un delete ad uno ad uno, perché non funziona?

    Grazie mille e un salutone

    Eugenio
  • Re: C++: vector<string *> e delete[]: errore

    skynet ha scritto:


    
    addrow(const std::vector && v)
    {
        vct = v;
    }
    
    Piccola svista:
    
    addrow(std::vector && v)  // senza il const
    {
        vct = v;
    }
    

    iugin ha scritto:


    Intendo, se nel vettore sono memorizzati indirizzi e io li passo ad un delete ad uno ad uno, perché non funziona?
    Stai usando l'operatore delete[] , che si usa solo per gli array.
    Per liberare singole locazioni (un puntatore alla volta) devi usare delete
    Quando sono davvero costretto? Io avevo l'impressione (guardando diversi esempi) che praticamente tutto si facesse con i puntatori...
    Il discorso è un po' lungo. Il C++ si è molto evoluto e ora la tendenza è usare apposite classi per la gestione dei puntatori. In generale queste classi sono conosciute come smart pointer e nello specifico del C++11/14 sono: shared_ptr e unique_ptr. Queste classi coprono circa il 90% dell'uso di puntatori grezzi all'interno di un programma.
    I rimanente 10% è quando proprio non se può fare a meno: costruzione di strutture dati tipo liste/stack fatti in casa, puntatori restituiti da librerie di terze parti o interfacciamento a funzioni C. I puntatori restano comunque fondamentali nel C++ moderno, solo che si preferisce inglobarli in strutture più intelligenti per non doverli gestire in prima persona: vector e string sono due esempi di come tali puntatori siano gestiti, dietro le quinte, da due strutture dati senza che tu debba preoccuparti dei loro puntatori interni.
  • Re: C++: vector<string *> e delete[]: errore

    Stai usando l'operatore delete[] , che si usa solo per gli array.
    Per liberare singole locazioni (un puntatore alla volta) devi usare delete
    avevo provato anche con delete ma non funzionava... se però mi dici che l'unico problema (nel mio concetto) erano le [], vuol dire che l'errore era da un'altra parte.
    Comunque ora il problema è risolto, con i vettori.
    Grazie anche per la risposta sugli smart pointer. Prima cerco però di spaccarmi la testa con i puntatori fino a capire bene il loro funzionamento e saperli usare anche in situazioni complesse.
    Certo che passare da Java a C++ è un bel macello

    Ciao a tutti

    Eugenio
Devi accedere o registrarti per scrivere nel forum
4 risposte