Newsgroup: it.comp.lang.c++
Titolo: dubbio

E' sbagliata questa dichiarazione in c++?
char *p;
p = new char[6];
p = "Item ";
Grazie a tutti! 



funziona, ma c'e' un errore.
char *p; // un puntatore a carattere
p = new char[6]; // tutto ok, hai riservato memoria per 6 char
		// e p punta al primo elemento
p = "Item ";	// ora p punta alla stringa costante "Item "
		// NON puoi piu' riferirti all'array
		// allocato prima. non puoi neanche deallocarlo
		// con delete!!!
chiaro?
ciao

p = "Item ";
Hai diverse soluzioni.
char *p;
p = new char[6];
strcpy (p,"Item ");
oppure (C puro)
char *p = "Item ";


questo non lo capito bene, quindi come si dovrebbe
scrivere per poi deallocarlo con delete?
Grazie pe la risposta. 

ok, ho capito
grazie ad entrambi :) 

 p = "Item ";
Quest'ultima non mi piace.
Cosa accade nel codice seguente?
char *p, *q;
{
   p = new char[6];
   q = "Item ";
}
*p = *q;
Non so cosa dice lo standard, ma non mi piace.
Kiuhnm

 p = "Item ";
Il miglior modo per non farti del male e' scrivere:
std::string p = "Item ";
Cosi' eviti di infognarti in problemi di gestione della memoria,  che
evidentemente e' un argomento col quale non hai dimestichezza ;-)
Ciao,
Nicola


ed infatti devo imparare a gestire la memoria, mi serve per forza.
Sto scrivendo in win32 un piccolo framework con una 20 di controlli
piano piano lo correggiamo.
Grazie ancora per i chiarimenti.

 Non so cosa dice lo standard, ma non mi piace.
Succede la stessa identica cosa che succederebbe in C se avessi
sostituito la new char[6] con una malloc.
Comunque nel codice di pippo c'è anche un'altro problema. Il tipo di
"Item " è const char*, mentre viene assegnato ad una variabile che è
solo char*. Se provo effettivamente ad accedere in scrittura a q (o lo
passo ad una funzione) il gcc sgama la cosa e da errore di compilazione.
IMHO è secondo standard.
-- 
Uccidete i filosofi e tenetevi riso e bacchette per voi.

 char *p = "Item ";
const char* p = "Item ";


 wrote in message 
news:1hb2cvn.1cib0f1v6is1nN%ri...@despammed.com...

Volevo solamente dire che utilizzo Dev c++ e non mi da errore di
compilazione, il dubbio era se accidentalmente andavo a scrivere
in una memoria non allocata.
Devo impostare qualcosa di particolare in dev c++ per fare
in modo che non prenda la sintassi che ho scritto?
Grazie. 

 sostituito la new char[6] con una malloc.
No, è l'altra riga a preoccuparmi. Cosa succede se si fa qualcosa di 
simile con un oggetto? L'oggetto non viene distrutto all'uscita dalla 
sezione di codice? Non conosco ancora i dettagli del C++.
Kiuhnm

 Il tipo di "Item " è const char*,
No, è const char[].
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg
The EMG Music page:         
http://www.emagsoftware.it/emgmusic
 


Intendi:
q = "Item ";
"Item " e' un array di caratteri statico, quindi sopravvive all'uscita
del blocco.
Ciao,
Nicola

 No, è const char[].
Mi fido :)


 sezione di codice? Non conosco ancora i dettagli del C++.
C++ non ha al momento un Garbage collector. Per la stringa ti ha
risposto Nicola. Per un oggetto generico esso  viene distrutto
automaticamente alla fine del blocco in cui è dichiarato.
Questo non vale però per gli oggetti allocati dinamicamente.
Questo programma genera come output:
=================== programma ========================
#include <iostream>
#include <ostream>
#include <string>
class MyClass
{
public:
    MyClass(std::string n) : name(n) {
        std::cout << "Object " << name << " constructed" << std::endl;
    }
    ~MyClass (){
        std::cout << "Object " << name << " destructed" << std::endl;
    }
 
    std::string name;
};
int main(){
    MyClass a("a");
    MyClass *d_a = new MyClass("d_a");
 
    {
        MyClass b("b");
        MyClass *d_b = new MyClass("d_b");
    }
    std::cout << "Exiting..." << std::endl;
    return 0;
}
================== output ===============================
Object a constructed
Object d_a constructed
Object b constructed
Object d_b constructed
Object b destructed
Exiting...
Object a destructed
Come vedi le variabili automatiche sono state deallocate alla fine del
blocco di definizione. Gli oggetti allocati dinamicamente invece no.
Questi sono dei memory leak, tanto quanto scordarsi di chiamare una free
per la memoria allocata con una *alloc.
Aggiungendo gli opportuni delete
===================== modificato ==========================
    MyClass a("a");
    MyClass *d_a = new MyClass("d_a");
 
    {
        MyClass b("b");
        MyClass *d_b = new MyClass("d_b");
        delete d_b;
    }
    std::cout << "Exiting..." << std::endl;
    delete d_a;
===================== output ==============================
Object a constructed
Object d_a constructed
Object b constructed
Object d_b constructed
Object d_b destructed
Object b destructed
Exiting...
Object d_a destructed
Object a destructed
È buona norma quando possibile utilizzare variabili automatiche, in
quanto queste sono gestite automaticamente (e anche in caso di
eccezioni, per esempio, gli oggetti sono correttamente distrutti quando
si risale lo stack di esecuzione.
Considera questo frammento
====================== con eccezione =======================
    try {
        MyClass e("e");
        MyClass *d_e = new MyClass("d_e");
        throw std::exception();
    } catch (std::exception) {
        std::cout << "Caught exception" << std::endl;
    }
=========================== ouput ==========================
Object e constructed
Object d_e constructed
Object e destructed
Caught exception
Assumendo che tutti gli oggetti si distruggano correttamente (chiamando
eventualmente la delete al loro interno per la memoria dinamica che
avessero allocato), in questo modo non si spreca memoria.
Prendi in considerazione anche questo codice:
======================== funzione bomba =====================
void boom(){
    try{
        MyClass e2("e2");
        MyClass *d_e2 = new MyClass("d_e2");
        throw std::exception(); 
    } catch (std::exception) {
        std::cout << "Caught exception" << std::endl;
        std::cout << "Rethrow!" << std::endl;
        throw;
    }   
}
========================= output =============================
Object e2 constructed
Object d_e2 constructed
Object e2 destructed
Caught exception
Rethrow!
terminate called after throwing an instance of 'std::exception'
  what():  St9exception
Abort trap
Ancora una volta l'oggetto e2 è stato distrutto correttamente, mentre
l'oggetto d_e2 no. Il codice corretto sarebbe stato:
======================== funzione bomba =====================
void boom(){
    MyClass *d_e2 = new MyClass("d_e2");;
    MyClass e2("e2");
    try{
        throw std::exception(); 
    } catch (std::exception) {
        std::cout << "Caught exception" << std::endl;
        delete d_e2;
        std::cout << "Rethrow!" << std::endl;
        throw;
    }   
}
int main(){
    try{
        boom();
    } catch (std::exception){
        std::cout << "Caught exception" << std::endl;
    }   
    return 0;
}
========================= output =======================
Object d_e2 constructed
Object e2 constructed
Caught exception
Object d_e2 destructed
Rethrow!
Object e2 destructed
Caught exception
Io poi sto includendo nei blocchi try codice che non necessariamente
andrebbe li, è tanto per capirsi. Una alternativa può essere l'uso di
auto_ptr o smart pointer più evolti ancora. auto_ptr è nella libreria
standard.
======================== auto_ptr =====================
int main(){
    MyClass a("a");
    std::auto_ptr<MyClass> a_a(new MyClass("a_a"));
 
    {
        MyClass b("b");
        std::auto_ptr<MyClass> a_b(new MyClass("a_b"));
    }
    std::cout << "Exiting..." << std::endl;
    return 0;
}
========================= output =======================
Object a constructed
Object a_a constructed
Object b constructed
Object a_b constructed
Object a_b destructed
Object b destructed
Exiting...
Object a_a destructed
Object a destructed


 sezione di codice? Non conosco ancora i dettagli del C++.
C++ non ha al momento un Garbage collector. Per la stringa ti ha


=================== programma ========================


};


================== output ===============================


Aggiungendo gli opportuni delete


===================== output ==============================


Considera questo frammento











======================== auto_ptr =====================


    return 0;
}

-- 
Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it.
    - Brian W. Kernighan

 Mi fido :)
Non ti fidare. Prova invece
std::cout << sizeof( "Item " ) << '\n';


 del blocco.
Ripensandoci, è vero, però mi sembra uno strappo (seppur comodo ed 
efficiente) alla regola.
Kiuhnm

 [...]
Avevi voglia di scrivere :)
Ho letto per rispetto nei tuoi confronti, ma veramente non c'era 
bisogno. E' difficile riuscire a creare progetti complessi in asm e in C 
come ho fatto per tanto tempo senza avere chiari certi concetti essenziali.
Il mio unico dubbio riguardava una forma che non ho mai usato.
Ricordo che anziché usare le stringhe sul posto, dichiaravo e definivo 
variabili globali (al limite statiche). Di fatto ottenevo lo stesso 
effetto perché sempre di variabili pre-inizializzate si trattava.
Kiuhnm

quello che avete scritto fino ad ora vale per 100 corsi. :)
e vai... :))) 

 fatto per tanto tempo senza avere chiari certi concetti essenziali.
Lo so. Tuttavia c'erano alcuni idiomi tipicamente C++ che potevi non
avere visto (per esempio auto_ptr, da quanto leggo dici di avere
iniziato da poco il C++, non su tutti i testi viene particolarmente
spiegato).
Comunque era tutto materiale piů o meno pronto per un articolo su un
blog (il codice) i commenti sono nuovi, ma vabbč. 
Inoltre tendenzialmente credo che spesso scrivendo risposte piů
esaustive anche se la persona cui non si risponde non ne ha bisogno, si
aiuti qualcun altro che legge e non pone domande, o qualcuno che
googolasse gli argomenti "a parte".
Peraltro riguardo alla stringa IMHO non viene trattata diversamente che
in C. Anche se AFAIK C++ non chiede esplicitamente cosa venga messo
nelle varie sezioni dell'eseguibile, dice semplicemente che non si
possono modificare (e di conseguenza č probabile che finiscano in
qualche zona read-only del codice oggetto).


 spiegato).
No, non li avevo mai visti, ma non è che mi abbiano colpito più di 
tanto. Penso che saprei farli senza problemi, pur non avendo ancora 
scritto praticamente niente in C++.
Ho letto in 7 giorni Thinking in C++, ma non ho fatto neanche un 
esercizio. Ogni volta che vedevo una nuova funzionalità del C++ pensavo 
a come implementarla in C, così penso di aver capito abbastanza bene i 
concetti.
Avrò senz'altro qualche lacuna, ma si vedrà. All'inizio penso che 
metterò "cout <<" ovunque in modo da evitare errori grossolani :)
Kiuhnm