Visualizzazione dei risultati da 1 a 10 su 17

Discussione: [C++] Classi

Hybrid View

  1. #1
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    177
    Quote Originariamente inviata da shodan Visualizza il messaggio
    Ancora meglio usando smart pointer (qui uso std::unique_ptr).
    Ma quindi tendenzialmente, se ho dati membro di una classe dichiarati come puntatori, conviene definirli come smart pointer, così evito nel distruttore di dover richiamare il delete, corretto?

    codice:
    class Classe
    {
      public:
        //costruttore, ecc;
        //il distruttore è
        ~Classe(){delete(puntatore);/*altre eventuali cose*/};
      private:
        //quello che serve
        tipoDelPuntatore* puntatore;
    }
    diventa
    codice:
    class Classe
    {
      public:
        //costruttore, ecc;
        //il distruttore è
        ~Classe(){/*altre eventuali cose, ma delete(puntatore) non dovrebbe servire più*/};
      private:
        //quello che serve
        std::unique_ptr<tipoDelPuntatore> puntatore;
    }
    Ne approfitto per una ulteriore domanda: se il dato membro di tipo puntatore sarà usato solo "interno" alla classe, uso unique_ptr, se invece sarà impiegato anche da qualche altro oggetto, uso shared_ptr, corretto?

    Grazie, grazie, grazie

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Quote Originariamente inviata da ing82 Visualizza il messaggio
    Ma quindi tendenzialmente, se ho dati membro di una classe dichiarati come puntatori, conviene definirli come smart pointer, così evito nel distruttore di dover richiamare il delete, corretto?
    Tendenzialmente si, ma non c'è una regola fissa: occorre valutare quello che si vuole fare.
    Lo shared_ptr mantiene un contatore interno di quante volte è stato copiato e l'ultimo a uscire cancella il puntatore, MA la memoria condivisa è la stessa. Se devi fare una deep copy dell'oggetto puntato lo devi fare esplicitamente.

    codice:
        shared_ptr<int> p = new int(10); // contatore = 1
        shared_ptr<int> q = p; // contatore = 2
        *q = 20; 
        cout << *p << endl; // 20 perché il puntatore interno è condiviso tra p e q.
    
        shared_ptr<int> z = new int;
        *z = *q;
        *q = 30;
    
        cout << *z << endl; // 20 perché il puntatore interno di z non è condiviso con p e q.
        cout << *p << endl; // 30 perché il puntatore interno è condiviso tra p e q.
    Con unique_ptr la faccenda è molto più semplice: non può essere copiato.
    codice:
        unique_ptr<int> p(new int(10))
        unique_ptr<int> q = p; // errore: unique_ptr non può essere copiato
    
        unique_ptr<int> q = std:move(p); // ma può essere spostato.
        // cout << *p << endl;  crash: il puntatore interno di p ora è nullptr
        cout << *q << endl; // vale 10.
    
        unique_ptr<int> z (new int);
        *z = *q;
    Ne approfitto per una ulteriore domanda: se il dato membro di tipo puntatore sarà usato solo "interno" alla classe, uso unique_ptr, se invece sarà impiegato anche da qualche altro oggetto, uso shared_ptr, corretto?
    Non proprio: userari shared_ptr se la tua classe dev'essere copiabile, quindi condividere il dato interno con copie di classe uguale; userai unique_ptr se non vuoi che la tua classe sia copiabile e quindi non condividere il dato interno con copie di classe uguale.
    Ambedue i puntatori possono essere restituiti da funzioni, ma se restituisci uno shared_ptr avrai il dato interno esistente, se usi uno unique_ptr stai dicendo: "classe X non devi più occuparti della gestione di unique_ptr<dato> perché ci pensa qualcun altro.

    Spero di essermi spiegato.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    177
    Quote Originariamente inviata da shodan Visualizza il messaggio
    Spero di essermi spiegato.
    Direi di sì. Il mio problema è la mancanza di esperienza, quindi dovrò ora fare qualche prova e capire con la pratica.
    Così a naso, direi che potrei partire usando unique_ptr (sempre riferito a dati membro di una classe) e quando mi accorgo che in realtà avrei fatto meglio ad usare shared_ptr, cambiare.

    Per ora grazie della disponibilità, ora faccio qualche prova.

  4. #4
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    177
    Prova n° 1

    codice:
    #include <iostream>
    #include <stdlib.h>
    #include <memory>
    
    using namespace std;
    
      class Prova
      {
        public:
          Prova(){cout<<"\nCreato l'oggetto Prova!";};
          ~Prova(){cout<<"\nDistrutto l'oggetto Prova!";};
          void run(){cout<<"\nProva is running!";};
          void pause(){cout<<"\nProva is paused!";};
          void termin(){cout<<"\nProva is terminated!";};
      };
    
      class Oggetto
      {
        public:
          Oggetto(){cout<<"\nCreato l'oggetto Oggetto!";};
          Oggetto(shared_ptr<Prova> puntatore):mProva(puntatore){cout<<"\nCreato l'oggetto Oggetto!";};
          ~Oggetto(){cout<<"\nDistrutto l'oggetto Oggetto!";};
          void run(){cout<<"\nOggetto is running!";mProva->run();};
          void pause(){cout<<"\nOggetto is paused!";mProva->pause();};
          void termin(){cout<<"\nOggetto is terminated!";mProva->termin();};
        private:
          shared_ptr<Prova> mProva;
      };
    
    int main()
    {
      {
        unique_ptr<Prova> prova(new Prova);
        prova->run();
        prova->pause();
        prova->run();
        prova->termin();
      }
      system("pause");
      return 0;
    }
    Al termine dell'esecuzione vedo che viene richiamato il distruttore di prova.
    Ultima modifica di ing82; 23-12-2015 a 23:31

  5. #5
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    177
    Prova n° 2

    codice:
    #include <iostream>
    #include <stdlib.h>
    #include <memory>
    
    using namespace std;
    
      class Prova
      {
        public:
          Prova(){cout<<"\nCreato l'oggetto Prova!";};
          ~Prova(){cout<<"\nDistrutto l'oggetto Prova!";};
          void run(){cout<<"\nProva is running!";};
          void pause(){cout<<"\nProva is paused!";};
          void termin(){cout<<"\nProva is terminated!";};
      };
    
      class Oggetto
      {
        public:
          Oggetto(){cout<<"\nCreato l'oggetto Oggetto!";};
          Oggetto(shared_ptr<Prova> puntatore):mProva(puntatore){cout<<"\nCreato l'oggetto Oggetto!";};
          ~Oggetto(){cout<<"\nDistrutto l'oggetto Oggetto!";};
          void run(){cout<<"\nOggetto is running!";mProva->run();};
          void pause(){cout<<"\nOggetto is paused!";mProva->pause();};
          void termin(){cout<<"\nOggetto is terminated!";mProva->termin();};
        private:
          shared_ptr<Prova> mProva;
      };
    
    int main()
    {
      {
        shared_ptr<Prova> prova(new Prova);
        prova->run();
        prova->pause();
        prova->run();
        prova->termin();
        system("pause");
        {
          unique_ptr<Oggetto> oggetto(new Oggetto(prova));
          oggetto->run();
          oggetto->pause();
          oggetto->run();
          oggetto->termin();
        }
        system("pause");
      }
      system("pause");
      return 0;
    }
    E così vedo che ad ogni fuori scope viene richiamato il distruttore corretto.

  6. #6
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    177
    Prova n° 3

    codice:
    #include <iostream>
    #include <stdlib.h>
    #include <memory>
    
    using namespace std;
    
      class Prova
      {
        public:
          Prova(){cout<<"\nCreato l'oggetto Prova!";};
          ~Prova(){cout<<"\nDistrutto l'oggetto Prova!";};
          void run(){cout<<"\nProva is running!";};
          void pause(){cout<<"\nProva is paused!";};
          void termin(){cout<<"\nProva is terminated!";};
      };
    
      class Oggetto
      {
        public:
          Oggetto(){cout<<"\nCreato l'oggetto Oggetto!";};
          Oggetto(shared_ptr<Prova> puntatore):mProva(puntatore){cout<<"\nCreato l'oggetto Oggetto!";};
          ~Oggetto(){cout<<"\nDistrutto l'oggetto Oggetto!";};
          void run(){cout<<"\nOggetto is running!";mProva->run();};
          void pause(){cout<<"\nOggetto is paused!";mProva->pause();};
          void termin(){cout<<"\nOggetto is terminated!";mProva->termin();};
        private:
          shared_ptr<Prova> mProva;
      };
    
    int main()
    {
      {
        shared_ptr<Prova> prova(new Prova);
        prova->run();
        prova->pause();
        prova->run();
        prova->termin();
        system("pause");
        {
          unique_ptr<Oggetto> oggetto(new Oggetto(prova));
          oggetto->run();
          oggetto->pause();
          oggetto->run();
          oggetto->termin();
          prova.reset();
          oggetto->run();
        }
        system("pause");
      }
      system("pause");
      return 0;
    }
    In questo modo vedo che dopo il reset, l'area puntata tramite prova, è comunque accessibile, perchè "shared" con oggetto, e alla prima chiusura di parentesi, vengono chiamati entrambi i distruttori.

    Restano da studiare i weak_ptr, ma buone vacanze.

    Auguri di un buon S. Natale a tutti!

  7. #7
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    177
    codice:
    #include <iostream>
    #include <stdlib.h>
    #include <memory>
    
    using namespace std;
    
      class Prova
      //Rappresenta un qualsiasi classe di cui deve essere creata un'istanza all'interno del programma
      {
        public:
          Prova(){numero=0;cout<<"\nProva is created!\nNumero = "<<numero<<"\n";};
          ~Prova(){cout<<"\nProva is destroyed!\nNumero = "<<numero<<"\n";};
          void run(){numero++;cout<<"\nProva is running!\nNumero = "<<numero<<"\n";};
          void pause(){cout<<"\nProva is paused!\nNumero = "<<numero<<"\n";};
          void termin(){numero=0;cout<<"\nProva is terminated!\nNumero = "<<numero<<"\n";};
        private:
          int numero;
      };
    
      class Oggetto
      //Rappresenta una classe di cui deve essere creata un'istanza all'interno del programma, ma in cui
      //uno dei dati membro è un puntatore a un altro oggetto.
      {
        public:
          Oggetto(){cout<<"\nOggetto is created!\n";};
          Oggetto(shared_ptr<Prova> puntatore){cout<<"\nOggetto is created!\n";mProva=puntatore;};
          ~Oggetto(){cout<<"\nOggetto is destroyed!\n";};
          void run(){cout<<"\nOggetto is running!";if(mProva.expired()){cout<<" But not Prova!\n";}else{auto temp=mProva.lock();cout<<"\n";temp->run();}};
          void pause(){cout<<"\nOggetto is paused!";if(mProva.expired()){cout<<" But not Prova!\n";}else{auto temp=mProva.lock();cout<<"\n";temp->pause();}};
          void termin(){cout<<"\nOggetto is terminated!";if(mProva.expired()){cout<<" But not Prova!\n";}else{auto temp=mProva.lock();cout<<"\n";temp->termin();}};
          void check(){if(mProva.expired()){cout<<"\nOggetto e' vuoto\n";}else{cout<<"\nOggetto e' pieno\n";}};
          void setWeakPointer(shared_ptr<Prova> puntatore){mProva=puntatore;};
        private:
          weak_ptr<Prova> mProva;
      };
    
    int main()
    {
      cout<<"\nCostruisco Oggetto come unique_ptr:\n";
      unique_ptr<Oggetto> oggetto(new Oggetto);
      cout<<"\nTesto l'oggetto Oggetto\n";
      oggetto->check();
      oggetto->run();
      oggetto->pause();
      oggetto->run();
      oggetto->termin();
      cout<<"\n";
      system("pause");
      {
        cout<<"\nCostruisco Prova:\n";
        shared_ptr<Prova> prova(new Prova);
        cout<<"\nTesto l'oggetto Prova\n";
        prova->run();
        prova->pause();
        prova->run();
        prova->termin();
        system("pause");
        cout<<"\nVerifico puntatore di oggetto:\n";
        oggetto->check();
        if(prova)
        {
          cout<<"\nProva e' pieno\n";
        }
        else
        {
          cout<<"\nProva e' vuoto\n";
        }
        system("pause");
        cout<<"\nProva.get "<<prova.get();
        cout<<"\nPasso Prova a Oggetto\n";
        oggetto->setWeakPointer(prova);
        cout<<"\nVerifico che ora oggetto abbia il riferimento a Prova\n";
        oggetto->check();
        system("pause");
        oggetto->run();
        oggetto->pause();
        oggetto->run();
        oggetto->termin();
        system("pause");
      }
      cout<<"\nLa parentesi e' stata chiusa\n";
      system("pause");
      cout<<"\nVerifico che oggetto abbia ancora il riferimento a Prova\n";
      oggetto->check();
      system("pause");
      oggetto->run();
      oggetto->pause();
      oggetto->run();
      oggetto->termin();
      system("pause");
    Pensavo di gestire la cosa in questo modo...consigli? Grazie

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.