Newsgroup: it.comp.lang.c++
Titolo: Dubbio sulla copia di stringhe

Salve ho creato la seguente classe:
typedef unsigned char BYTE; // definizione del tipo BYTE
typedef unsigned char BIT;  // definizione del tipo BIT
class bitstring {
      BYTE byte_buffer; // byte d'appoggio in cui vengono scritti i bit
      int  num_bit;     // numero di bit che sono contenuti in
byte_buffer
      int  num_byte;    // numero di byte scritti sulla stringa
      int  bit_offset;  
   public:
      int DIM;          // dimensione della stringa
      unsigned char *stringa;
      bitstring(int) ;          
      bitstring(unsigned char *); // costruttore, copia la stringa
passata.
      ~bitstring() ;           // distruttore 
      void  scrivi_bit(BIT) ;  // accoda un bit alla stringa
      BIT leggi_bit(int);      // legge il bit nella posizione
indicata        
      void scrivi_byte(BYTE);  // accoda un byte alla stringa
      BYTE leggi_byte (int);   // legge un byte dalla stringa
      void svuota_buffer();    // scrive il byte_buffer sulla stringa
      int lunghezza_bit() ;    // lunghezza in bit
      int lunghezza_byte();    // lunghezza in byte
};
Ho recentemente aggiunto il secondo costruttore di cui riporto il
codice:
bitstring:: bitstring (unsigned char * str)
{
   int len =strlen((char *)str);
   stringa =new (unsigned char [len]);
   strcpy ((char *)stringa,(char *)str);
   byte_buffer=0;
   num_bit=len*8;
   num_byte=len;
   bit_offset=0;
   DIM=len;
} 
Sostanzialmente deve copiare la stringa str, in bitstring.stringa, per
fare questo ho usato le funzioni di cstring, il problema e' che operano
su char e non su unsigned char, per questo ho usato dei cast.
Mi chiedo, questo puo' in qualche modo modificare i valori che vado a
copiare?
Inoltre il modo di copiare la stringa che ho usato e' corretto oppure
no?
-- 
Nemesis at work

 no?
Questa domanda resta comunque valida. In attesa di vostri suggerimenti
vi ringrazio in anticipo.
-- 
Nemesis at work

>    stringa =new (unsigned char [len]);
Al di la' della classe di per se (usare std::string no ?) occhio che non
passi strlen(str)+1. Poi non hai definito l'operatore = da nessuna parte, e
di default il compilatore te ne crea uno che i campi li copia a mano (quindi
anche i puntatori) e se mai faresti un'assegnazione potresti ritrovarti nel
cattivo caso di avere due classi che puntano alla stessa stringa. Cmq lo
strcpy andava benissimo se i buffer erano a priori corretti e non c'era
nessuna modifica dei dati in memoria ; invece controlla se ti passano NULL
in quel caso crea una stringa di [1] carattere e assegnagli 0.
ciau
-Nicola e "questo" e "quell'altro" non sarebbe male cambiarli .. ;) ..
std::string proprio no?

std::string proprio no?
Beh magari alla prossima revisione della classe ;)
-- 
   _  __                  _    || L' estate svuota la mente e cosě
  / |/ /__ __ _  ___ ___ (_)__ || mi ritrovo senza uno straccio di
 /    / -_)  ' \/ -_(_-</ (_-< || idea  per riempire questo spazio
/_/|_/\__/_/_/_/\__/___/_/___/ || bianco ...

l'operatore =, sempre per motivi di tempo e cmq non ne ho bisogno.
In questo caso e' allora preferibile impedire che venga generato
quello di default (che farebbe danni). A parte il tuo caso (in cui
l'operazione di assegnazione semplicemente "non ti serve") ci sono
contesti in cui "copiare" un oggetto non ha proprio senso (es.
un file o una finestra GUI); quando ci si trova in questa
situazione si fa di solito cosi'...
   class MyClass
   {
     public:
       MyClass( ... ); // mio costruttore
       ... altri metodi della mia classe ...
     private:
       MyClass(const MyClass&); // NON DEFINITO
       MyClass& operator=(const MyClass&); // NON DEFINITO
   };
Mettendo la dichiarazione il compilatore non sintetizzera' la
versione di default (pericolosa) e gli utenti della classe
otterranno un errore di violazione dei permessi di accesso
se dovessero cercare di copiare una istanza.
Se invece inavvertitamente questa copia viene chiesta
nell'implementazione di un metodo della classe (che quindi
non ha problemi ad accedere a membri "private") comunque
otterresti un errore in fase di link.
Visto che costa solo un paio di linee di codice non credo
che si possa accampare la scusa "avevo fretta" :) ...
tieni presente che e' molto facile tirare in ballo le
operazioni di copia implicitamente (es usando container
STL oppure passando parametri per valore) e magari questa
cosa succedera' fra tre anni quando nemmeno ti ricorderai
se questo programma lo hai scritto tu o un tuo collega.
Nota anche che quando qualcuno vede l'interfaccia di una
classe che ad esempio dichiara un distruttore ma non
dichiara gli operatori di copia sorge sempre un dubbio
terribile: andra' bene la versione di default oppure
l'autore si e' scordato di definire una versione corretta ?
Per questa ragione nelle classi (non banali) in cui ti
vanno bene le versioni membro-a-membro generate
automaticamente dal compilatore almeno un commento del
tipo "per la copia vanno bene le versioni di default"
andrebbe messo. Cosi' l'utilizzatore e' piu' tranquillo :) ...
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

che si possa accampare la scusa "avevo fretta" :) ...
In effetti penso che si possa fare ;)
quindi metto solo la dichiarazione nell'header senza perň definirlo.
