Discussione:
Scambio di due variabili con puntatore
(troppo vecchio per rispondere)
Osvald
2013-04-13 10:07:41 UTC
Permalink
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
di un puntatore:

======================================

// Scambio di due variabili di tipo intero

#include <iostream>
using namespace std;
int main()
{

int x=10,y=20;

int* p_x=NULL;

p_x=new int;

*p_x=x;

x=y;
y=*p_x;

delete p_x;

cout<<"x="<<x<<endl<<"y="<<y;

return 0;

}

===============================

Con i puntatori, se ho ben capito, è possibile, un uso dinamico della
memoria; e' possibile cioe', allocare e deallocare spazi di memoria
(memoria heap);

se nel predetto programma NON avessi usato il puntatore, ma una
semplice variabile di appoggio(utilizzo memoria stack) di tipo intero
(per eseguire lo scambio delle varabili intere x e y), il programma
sarebbe stato meno ottimizzato dal punto di vista dell'impiego di
memoria?


Ciao e grazie milleeeeee!
f***@gmail.com
2013-04-13 12:36:40 UTC
Permalink
Post by Osvald
Con i puntatori, se ho ben capito, è possibile, un uso dinamico della
memoria; e' possibile cioe', allocare e deallocare spazi di memoria
(memoria heap);
Un puntatore può tenere NULL oppure un indirizzo di memoria.

Gli operatori (e le funzioni) di allocazione riservano uno spazio nella memoria
dinamica e ritornano un puntatore.
Post by Osvald
se nel predetto programma NON avessi usato il puntatore, ma una
semplice variabile di appoggio(utilizzo memoria stack) di tipo intero
(per eseguire lo scambio delle varabili intere x e y), il programma
sarebbe stato meno ottimizzato dal punto di vista dell'impiego di
memoria?
Avrebbe usato memoria automatica invece di dinamica.

Su quale tipo di memoria si meglio usare e quale soluzione sia più leggera
per il processore nei vari casi lo lascio pensare a te (ma non cercare di
farti un'idea generale, solitamente dipende dal caso specifico).

Ciao!
enoquick
2013-04-13 15:01:18 UTC
Permalink
Post by Osvald
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
======================================
// Scambio di due variabili di tipo intero
#include <iostream>
using namespace std;
int main()
{
int x=10,y=20;
int* p_x=NULL;
p_x=new int;
*p_x=x;
x=y;
y=*p_x;
delete p_x;
cout<<"x="<<x<<endl<<"y="<<y;
return 0;
}
===============================
Con i puntatori, se ho ben capito, è possibile, un uso dinamico della
memoria; e' possibile cioe', allocare e deallocare spazi di memoria
(memoria heap);
se nel predetto programma NON avessi usato il puntatore, ma una
semplice variabile di appoggio(utilizzo memoria stack) di tipo intero
(per eseguire lo scambio delle varabili intere x e y), il programma
sarebbe stato meno ottimizzato dal punto di vista dell'impiego di
memoria?
Ciao e grazie milleeeeee!
Fra stack e heap i costi di accesso sono uguali
La differenza sta che new (o malloc in C) ha un costo ben superiore all'
allocazione di una variabile nello stack e per simmetria anche delete (o
free in C)
Osvald
2013-04-13 15:25:27 UTC
Permalink
Post by enoquick
Post by Osvald
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
======================================
// Scambio di due variabili di tipo intero
#include <iostream>
using namespace std;
int main()
{
int x=10,y=20;
int* p_x=NULL;
p_x=new  int;
*p_x=x;
x=y;
y=*p_x;
delete p_x;
cout<<"x="<<x<<endl<<"y="<<y;
return 0;
}
===============================
Con i puntatori, se ho ben capito, è possibile, un uso dinamico della
memoria; e' possibile cioe',  allocare e deallocare spazi di memoria
(memoria heap);
  se nel predetto programma NON avessi usato il puntatore, ma una
semplice variabile di appoggio(utilizzo memoria stack) di tipo intero
(per eseguire lo scambio delle varabili intere x e y), il programma
sarebbe stato meno ottimizzato dal punto di vista dell'impiego di
memoria?
Fra stack e heap i costi di accesso sono uguali
La differenza sta che new (o malloc in C) ha un costo ben superiore all'
allocazione di una variabile nello stack e per simmetria anche delete (o
free in C)
Quindi, nel caso in esame, sarebbe stato meglio NON utilizzare il
puntatore?....stavo cercando di capire quando potesse essere piu'
conveniente l'uso dei puntatori...ma forse sto cercando di andare
troppo oltre quelle che sono le conoscenze al momento acquisite...cmq
chiedo SCUSA al ng se a volte faccio domande banali e vi ringrazio per
i vostri preziosi suggerimenti.

Ciao e grazie mille!!
Soviet_Mario
2013-04-13 15:39:40 UTC
Permalink
Post by Osvald
Post by enoquick
Post by Osvald
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
======================================
// Scambio di due variabili di tipo intero
#include<iostream>
using namespace std;
int main()
{
int x=10,y=20;
int* p_x=NULL;
p_x=new int;
*p_x=x;
x=y;
y=*p_x;
delete p_x;
cout<<"x="<<x<<endl<<"y="<<y;
return 0;
}
===============================
Con i puntatori, se ho ben capito, è possibile, un uso dinamico della
memoria; e' possibile cioe', allocare e deallocare spazi di memoria
(memoria heap);
se nel predetto programma NON avessi usato il puntatore, ma una
semplice variabile di appoggio(utilizzo memoria stack) di tipo intero
(per eseguire lo scambio delle varabili intere x e y), il programma
sarebbe stato meno ottimizzato dal punto di vista dell'impiego di
memoria?
Fra stack e heap i costi di accesso sono uguali
La differenza sta che new (o malloc in C) ha un costo ben superiore all'
allocazione di una variabile nello stack e per simmetria anche delete (o
free in C)
Quindi, nel caso in esame, sarebbe stato meglio NON utilizzare il
puntatore?....
ovviamente !

sarebbe stato più efficace fare

int x=10,y=20;

int tmp=x;

x=y;

y=tmp;


I puntatori, ma anche le reference (unitamente ad un uso
oculato dell'attributo "const"), ti servono per l'efficienza
non tanto quando VUOI copiare dei dati, ma quando NON vuoi
copiarli.
Ad es. nel passaggio di parametri a una funzione, se si
tratta di oggetti molto grandi, il passaggio by value, che
richiede una copia ed è il default, può diventare troppo
lento, oltre a consumare più memoria stack. Il passaggio per
indirizzo (puntatore o reference) risparmia sia la memoria
sia il tempo di copia.
Se i parametri sono di sola lettura, l'attributo "const" ti
supporta nell'evitare di modificarli per errore.
Un passaggio per indirizzo con puntatore o reference
diversamente è una sorta di indicazione che la funzione
vuole modificare lo stato di parametri ricevuti, come
"effetto collaterale voluto", ma non può ritornare tutte le
sue elaborazioni nel solo valore di ritorno.

Sostanzialmente i puntatori e le reference hanno un senso
quando si entra ed esce da scope diversi ... nello stesso
blocco (scope) usare un puntatore non mi sembra avere quel
gran senso, salvo considerare come puntatore anche il nome
di un array.
Post by Osvald
stavo cercando di capire quando potesse essere piu'
conveniente l'uso dei puntatori...ma forse sto cercando di andare
troppo oltre quelle che sono le conoscenze al momento acquisite...cmq
non mi pare che sia mai abbastanza presto per capire i pro e
contro dei puntatori in C++, visto che sono uno dei punti
caratteristici del linguaggio.
Cerca anche pian piano di capire il senso delle reference,
che nell'USO sono più facili da usare dei puntatori, ma sono
anche meno flessibili nell'assegnazione.

Sempre a proposito dei puntatori, sappi che l'uso di
new/delete comporta di farsi carico del corretto rilascio
delle risorse in caso di errori irreversibili che dovessero
capitare tra una new e la corrispettiva delete, e
nell'accedere a una variabile istanziata (a meno di non
avere già gestito, e bene, gli errori, tipo nei
costruttori), validare i puntatori prima di usarli ciecamente.
Se crei un puntatore ma new ritorna NULL, devi testare il
valore dello stesso prima di usare l'oggetto, perché
potrebbe non esistere nessun oggetto.

ciao
CCCP
Post by Osvald
chiedo SCUSA al ng se a volte faccio domande banali e vi ringrazio per
i vostri preziosi suggerimenti.
Ciao e grazie mille!!
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
f***@gmail.com
2013-04-13 15:49:02 UTC
Permalink
Post by Osvald
Quindi, nel caso in esame, sarebbe stato meglio NON utilizzare il
puntatore?....
Nel caso in esame sì, molto meglio una normalissima variabile.
Post by Osvald
stavo cercando di capire quando potesse essere piu'
conveniente l'uso dei puntatori...ma forse sto cercando di andare
troppo oltre quelle che sono le conoscenze al momento acquisite...
Probabilmente sì, ma la "rule of thumb" in questi casi è facile: usa sempre
memoria automatica a meno che 1- non hai idea della dimensione che ti serve
se non a runtime o 2- non hai spazio sullo stack (o, equivalmentemente, pensi
che ci siano casi in cui puoi sforare).

Facendo così hai meno controlli da fare (ogni allocazione prevede un check),
devi fare meno deallocazioni (e quindi puoi fare meno errori), diminuisci il
rischio di corruzione della memoria (anche se non ti salvi dagli stessi
problemi con lo stack, che però in generale tendono ad essere minori), sai
che la memoria è riservata e rendi quindi un po' più robusto il programma in
caso di memoria scarsa.
Post by Osvald
cmq
chiedo SCUSA al ng se a volte faccio domande banali e vi ringrazio per
i vostri preziosi suggerimenti.
Si dice spesso che "non esistono domande stupide, solo le risposte possono
esserlo".
Per questo alla fine la risposta l'avrai sempre, ma a volte ci si altera quando
la domanda è relativa ad una cosa che chi domanda dovrebbe sapere ;)

Ciao!
enoquick
2013-04-13 19:51:33 UTC
Permalink
Post by Osvald
Post by enoquick
Post by Osvald
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
======================================
// Scambio di due variabili di tipo intero
#include <iostream>
using namespace std;
int main()
{
int x=10,y=20;
int* p_x=NULL;
p_x=new int;
*p_x=x;
x=y;
y=*p_x;
delete p_x;
cout<<"x="<<x<<endl<<"y="<<y;
return 0;
}
===============================
Con i puntatori, se ho ben capito, è possibile, un uso dinamico della
memoria; e' possibile cioe', allocare e deallocare spazi di memoria
(memoria heap);
se nel predetto programma NON avessi usato il puntatore, ma una
semplice variabile di appoggio(utilizzo memoria stack) di tipo intero
(per eseguire lo scambio delle varabili intere x e y), il programma
sarebbe stato meno ottimizzato dal punto di vista dell'impiego di
memoria?
Fra stack e heap i costi di accesso sono uguali
La differenza sta che new (o malloc in C) ha un costo ben superiore all'
allocazione di una variabile nello stack e per simmetria anche delete (o
free in C)
Quindi, nel caso in esame, sarebbe stato meglio NON utilizzare il
puntatore?....stavo cercando di capire quando potesse essere piu'
conveniente l'uso dei puntatori...ma forse sto cercando di andare
troppo oltre quelle che sono le conoscenze al momento acquisite...cmq
chiedo SCUSA al ng se a volte faccio domande banali e vi ringrazio per
i vostri preziosi suggerimenti.
Ciao e grazie mille!!
Puntatori e memoria dinamica (heap) non sono la stessa cosa
Quindi le domande dovrebbero essere due:
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Osvald
2013-04-13 21:27:05 UTC
Permalink
Post by enoquick
Post by Osvald
Post by enoquick
Post by Osvald
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
======================================
// Scambio di due variabili di tipo intero
#include <iostream>
using namespace std;
int main()
{
int x=10,y=20;
int* p_x=NULL;
p_x=new  int;
*p_x=x;
x=y;
y=*p_x;
delete p_x;
cout<<"x="<<x<<endl<<"y="<<y;
return 0;
}
===============================
Con i puntatori, se ho ben capito, è possibile, un uso dinamico della
memoria; e' possibile cioe',  allocare e deallocare spazi di memoria
(memoria heap);
   se nel predetto programma NON avessi usato il puntatore, ma una
semplice variabile di appoggio(utilizzo memoria stack) di tipo intero
(per eseguire lo scambio delle varabili intere x e y), il programma
sarebbe stato meno ottimizzato dal punto di vista dell'impiego di
memoria?
Fra stack e heap i costi di accesso sono uguali
La differenza sta che new (o malloc in C) ha un costo ben superiore all'
allocazione di una variabile nello stack e per simmetria anche delete (o
free in C)
Quindi, nel caso in esame, sarebbe stato meglio NON utilizzare il
puntatore?....stavo cercando di capire quando potesse essere piu'
conveniente l'uso dei puntatori...ma forse sto cercando di andare
troppo oltre quelle che sono le conoscenze al momento acquisite...cmq
chiedo SCUSA al ng se a volte faccio domande banali e vi ringrazio per
i vostri preziosi suggerimenti.
Ciao e grazie mille!!
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
utilizzare la memoria dinamica....l' esempio al link:

http://www.cplusplus.com/doc/tutorial/dynamic/

potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.

Ciao e grazie mille!
enoquick
2013-04-13 22:10:40 UTC
Permalink
Post by Osvald
Post by enoquick
Post by Osvald
Post by enoquick
Post by Osvald
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
======================================
// Scambio di due variabili di tipo intero
#include <iostream>
using namespace std;
int main()
{
int x=10,y=20;
int* p_x=NULL;
p_x=new int;
*p_x=x;
x=y;
y=*p_x;
delete p_x;
cout<<"x="<<x<<endl<<"y="<<y;
return 0;
}
===============================
Con i puntatori, se ho ben capito, è possibile, un uso dinamico della
memoria; e' possibile cioe', allocare e deallocare spazi di memoria
(memoria heap);
se nel predetto programma NON avessi usato il puntatore, ma una
semplice variabile di appoggio(utilizzo memoria stack) di tipo intero
(per eseguire lo scambio delle varabili intere x e y), il programma
sarebbe stato meno ottimizzato dal punto di vista dell'impiego di
memoria?
Fra stack e heap i costi di accesso sono uguali
La differenza sta che new (o malloc in C) ha un costo ben superiore all'
allocazione di una variabile nello stack e per simmetria anche delete (o
free in C)
Quindi, nel caso in esame, sarebbe stato meglio NON utilizzare il
puntatore?....stavo cercando di capire quando potesse essere piu'
conveniente l'uso dei puntatori...ma forse sto cercando di andare
troppo oltre quelle che sono le conoscenze al momento acquisite...cmq
chiedo SCUSA al ng se a volte faccio domande banali e vi ringrazio per
i vostri preziosi suggerimenti.
Ciao e grazie mille!!
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Ciao e grazie mille!
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
Osvald
2013-04-13 22:21:22 UTC
Permalink
[cut]
Post by enoquick
Post by Osvald
Post by enoquick
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori  ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
OK...puoi, fare qualche esempio *semplice* (*se possibile*) di
convenienza dell'uso dei puntatori senza l'impiego della memoria
dinamica?

Ciao e grazie milleeeeeee!
Soviet_Mario
2013-04-13 22:24:28 UTC
Permalink
Post by Osvald
[cut]
Post by enoquick
Post by Osvald
Post by enoquick
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
OK...puoi, fare qualche esempio *semplice* (*se possibile*) di
convenienza dell'uso dei puntatori senza l'impiego della memoria
dinamica?
prova a pensare di avere una funzione che fa una divisione
tra interi e restituisce SIA il quoziente SIA il resto.
Come faresti ?
Post by Osvald
Ciao e grazie milleeeeeee!
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Soviet_Mario
2013-04-13 22:25:19 UTC
Permalink
Post by Osvald
[cut]
Post by enoquick
Post by Osvald
Post by enoquick
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
OK...puoi, fare qualche esempio *semplice* (*se possibile*) di
convenienza dell'uso dei puntatori senza l'impiego della memoria
dinamica?
prova a pensare di avere una funzione che fa una divisione tra interi e
restituisce SIA il quoziente SIA il resto.
Come faresti ?
ah ... aggiungo di farlo senza creare una struct ad hoc che
incapsuli il doppio dato. Funzione che usi soltanto i tipi
nativi
Post by Osvald
Ciao e grazie milleeeeeee!
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Osvald
2013-04-14 00:34:12 UTC
Permalink
Post by Soviet_Mario
Post by Osvald
[cut]
Post by enoquick
Post by Osvald
Post by enoquick
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
OK...puoi, fare qualche esempio *semplice* (*se possibile*) di
convenienza dell'uso dei puntatori senza l'impiego della memoria
dinamica?
prova a pensare di avere una funzione che fa una divisione tra interi e
restituisce SIA il quoziente SIA il resto.
Come faresti ?
ah ... aggiungo di farlo senza creare una struct ad hoc che
incapsuli il doppio dato. Funzione che usi soltanto i tipi
nativi
Credo di essere riuscito a farlo ma senza l'uso dei puntatori :-((

==============================================

#include <iostream>
using namespace std;

void divisione (int a, int b, int& risdiv,int& resto)
{

risdiv = a/b;

resto = a%b;

}

int main ()
{
int risdiv=0;
int resto=0;

divisione(9,2,risdiv,resto);

cout << "Risultato_div=" << risdiv << endl;
cout << "Resto=" << resto << endl;

return 0;
}

==========================================================


..con l'uso dei puntatori ho ottenuto degli errori ...appena possibile
riprovo, *adesso cerco di dormire, se ci riesco*...:-(((....

cmq, trovo molto interessante l'esrcizio che hai proposto.

Ciao e grazie MILLEEEEEEEE!
Osvald
2013-04-14 09:07:13 UTC
Permalink
Post by Osvald
Post by Soviet_Mario
Post by Osvald
[cut]
Post by enoquick
Post by Osvald
Post by enoquick
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
OK...puoi, fare qualche esempio *semplice* (*se possibile*) di
convenienza dell'uso dei puntatori senza l'impiego della memoria
dinamica?
prova a pensare di avere una funzione che fa una divisione tra interi e
restituisce SIA il quoziente SIA il resto.
Come faresti ?
ah ... aggiungo di farlo senza creare una struct ad hoc che
incapsuli il doppio dato. Funzione che usi soltanto i tipi
nativi
Credo di essere riuscito a farlo ma senza l'uso dei puntatori :-((
==============================================
#include <iostream>
using namespace std;
void divisione (int a, int b, int& risdiv,int& resto)
{
  risdiv = a/b;
  resto = a%b;
  }
int main ()
{
  int risdiv=0;
  int resto=0;
 divisione(9,2,risdiv,resto);
 cout << "Risultato_div=" << risdiv << endl;
 cout << "Resto=" << resto << endl;
 return 0;
}
==========================================================
..con l'uso dei puntatori ho ottenuto degli errori ...appena possibile
riprovo, *adesso cerco di dormire, se ci riesco*...:-(((....
cmq, trovo molto interessante l'esrcizio che hai proposto.
Ho provato con i puntatori, ma, durante l'esecuzione del programma,
compare la finestra windows:

"Prova.exe ha smesso di funzionare. Si e' verificato un problema che
impedisce il finzionamento corretto del programma.Chiudere il
programma."

Lanciando il debug mi compare il seguente messaggio (Finestra Call
stack):

#0 004013A8 main() (C:\Users\programmi\Desktop\Prova\main.cpp:28)

Il programma e' il seguente:

===========================================


#include <iostream>
using namespace std;

void divisione (int a, int b, int* p1,int *p2 )
{

int risdiv;
int resto;

p1=&risdiv;

p2=&resto;

risdiv = a/b;

resto = a%b;

}

int main ()
{
int* p1=NULL ;
int* p2=NULL ;

divisione(9,2,p1,p2);

cout << "Risultato_div=" << *p1 << endl;
cout << "Resto=" << *p2 << endl;

return 0;
}

===========================================

La linea 28 segnalata dalla finestra "Call stack", corrisponde
all'istruzione:

cout << "Risultato_div=" << *p1 << endl;

....dove sbaglio e a cosa e' dovuto la segnalazione di errore che
ottengo?

Ciao e grazie milleeee!
Soviet_Mario
2013-04-14 10:42:05 UTC
Permalink
Post by Osvald
Post by Osvald
Post by Soviet_Mario
Post by Osvald
[cut]
Post by enoquick
Post by Osvald
Post by enoquick
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
OK...puoi, fare qualche esempio *semplice* (*se possibile*) di
convenienza dell'uso dei puntatori senza l'impiego della memoria
dinamica?
prova a pensare di avere una funzione che fa una divisione tra interi e
restituisce SIA il quoziente SIA il resto.
Come faresti ?
ah ... aggiungo di farlo senza creare una struct ad hoc che
incapsuli il doppio dato. Funzione che usi soltanto i tipi
nativi
Credo di essere riuscito a farlo ma senza l'uso dei puntatori :-((
senze ACCORGERTI di usare puntatori intendi dire : le
reference SONO puntatori, semplicemente con alcune
peculiarità, tipo l'accesso con semantica "plain" di alias
di nomi di variabili, e la costanza di indirizzo (che il
puntatore non ha necessariamente, essendo riciclabile).
Ma per il resto le reference SONO indirizzi quanto lo sono i
puntatori classici.
Post by Osvald
Post by Osvald
==============================================
#include<iostream>
using namespace std;
void divisione (int a, int b, int& risdiv,int& resto)
{
risdiv = a/b;
resto = a%b;
}
int main ()
{
int risdiv=0;
int resto=0;
divisione(9,2,risdiv,resto);
cout<< "Risultato_div="<< risdiv<< endl;
cout<< "Resto="<< resto<< endl;
return 0;
}
okay, nell'esercizio dopo invece c'è ... un po' da mettersi
le mani nei capelli. Vediamolo
Post by Osvald
Post by Osvald
==========================================================
..con l'uso dei puntatori ho ottenuto degli errori ...appena possibile
riprovo, *adesso cerco di dormire, se ci riesco*...:-(((....
cmq, trovo molto interessante l'esrcizio che hai proposto.
bene, infatti è "cannato", ma è cannando che si capisce
qualcosa anche, basta capire cosa c'è di sbagliato
Post by Osvald
Ho provato con i puntatori, ma, durante l'esecuzione del programma,
"Prova.exe ha smesso di funzionare. Si e' verificato un problema che
impedisce il finzionamento corretto del programma.Chiudere il
programma."
Lanciando il debug mi compare il seguente messaggio (Finestra Call
#0 004013A8 main() (C:\Users\programmi\Desktop\Prova\main.cpp:28)
===========================================
#include<iostream>
using namespace std;
void divisione (int a, int b, int* p1,int *p2 )
{
int risdiv;
int resto;
queste dichiarazioni sono già molto sospette del fatto di
non avere capito che gli oggetti BERSAGLIO la funzione
doveva riceverli dall'esterno, tramite i parametri puntatore.
Invece ricrei due oggetti, che sono temporanei, nello
stackframe della funzione, e che quindi SVANIRANNO al return.
Non c'è nessuna ragione di dichiarare due temporanei per una
funzione simile (non in generale).
Ma l'orrore tra poco ...
Post by Osvald
p1=&risdiv;
p2=&resto;
questa è una delle cose peggiori da leggere : stai ricavando
l'indirizzo a due oggetti temporanei (morituri te salutant),
e ti appresti a passarli fuori della funzione ... se non
che, non li passi nemmeno fuori.
Cmq, sin qui l'errore è avere preso l'indirizzo di due
variabili evanescenti, indirizzo che diventerebbe una mina
vagante se uscisse dalla funzione e qualcuno ci scrivesse
sopra, perché gli oggetti puntati sono svaniti.
Non è finita
Post by Osvald
risdiv = a/b;
resto = a%b;
qui esegui un calcolo inutile. Assegnare le variabili locali
automatiche svanisce appena fuori della funzione.


* gli oggetti puntati originariamente dai due argomenti (che
si supponevano essere stati inizializzati dal CHIAMANTE) non
sono mai stati scritti.
Infatti per scrivere nell'oggetto non devi usare

p1 = etc etc;

ma

*p1 = etc etc;

devi DEREFERENZIARE il puntatore, ossia indirizzare
l'oggetto puntato.

scrivendo p1=qualcosa ottieni solo di perdere l'indirizzo
che era stato passato dal chiamante (in teoria), e senza
aver toccato l'oggetto bersaglio.

inoltre l'effetto rimane LOCALE alla funzione chiamata,
infatti essa riceve come argomento UNA COPIA per valore
dell'indirizzo. Se anche tu localmente la alteri
(scollegandoti dal chiamante), globalmente l'indirizzo di
memoria non viene alterato di certo. Semplicemente la
funzione non vede più il suo oggetto originale, ma per come
l'hai scritto vede in modo diverso un oggetto locale
automatico, già in scope.
Post by Osvald
}
int main ()
{
int* p1=NULL ;
int* p2=NULL ;
divisione(9,2,p1,p2);
ecco, la filosofia è totalmente diversa.

int p1, p2; // allochi DUE OGGETTI REALI, non puntatori al vuoto

divisione(9, 2, & p1, & p2);
// invochi passando gli indirizzi di tali oggetti
// in modo che la funzione possa vedere cose create
// dal chiamante
Post by Osvald
cout<< "Risultato_div="<< *p1<< endl;
l'errore scatta qui : stai passando NULL a cout.
Infatti la modifica ai puntatori fatta dentro divisione
rimane locale, i puntatori vengono passati byval, a meno di
non usare l'indirizzo dei puntatori, e nella funzione
passare **arg (è un uso che per il momento non ti serve di
sicuro).
Post by Osvald
cout<< "Resto="<< *p2<< endl;
anche qui passi NULL


Quindi di norma la funzione chiamata non alloca niente, ma
riceve gli indirizzi di oggetti bersaglio, e li usa
dereferenziandoli per registrare colà i suoi risultati.

Se invece la funzione chiamata deve ALLOCARE lei memoria e
ritornare un oggetto, allora lì devi usare per forza la
memoria dinamica heap, il cui life-cycle è a gestione manuale.
Non ritornare mai indirizzi di variabili AUTOMATICHE fuori
dalla funzione che le ha dichiarate, perché perdono validità
al return e detti oggetti sono sovrascritti o cmq invalidati.

In questo caso è più semplice restituire l'indirizzo nel
valore di ritorno, diversamente devi usare una reference a
un argomento puntatore, o un argomento puntatore a puntatore
e dereferenziarlo.


double * CreaResultQuadrato (double Val)
{
try {
double * ResultPtr = new double;
// la variabile creata, anonima, ha vita "manuale"
} catch (...) // se fallisce allocazione
{
return (double *) 0;
};
* ResultPtr = Val * Val;
// dereferenzia -> accede al double dinamico
return ResultPtr; // ritorna l'indirizzo
}

void main (void)
{
double * SquarePtr = CreaResultQuadrato (2.0);
if (SquarePtr != (double *) 0)
cout << (* SquarePtr);
else
count << "epic fail !";
return;
}


potresti provare a restituire l'oggetto via argomenti e non
via valore di ritorno ...
ciao
CCCP
Post by Osvald
return 0;
}
===========================================
La linea 28 segnalata dalla finestra "Call stack", corrisponde
cout<< "Risultato_div="<< *p1<< endl;
.....dove sbaglio e a cosa e' dovuto la segnalazione di errore che
ottengo?
Ciao e grazie milleeee!
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Osvald
2013-04-14 10:53:04 UTC
Permalink
Post by Osvald
Post by Osvald
Post by Soviet_Mario
Post by Osvald
[cut]
Post by enoquick
Post by Osvald
Post by enoquick
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
OK...puoi, fare qualche esempio *semplice* (*se possibile*) di
convenienza dell'uso dei puntatori senza l'impiego della memoria
dinamica?
prova a pensare di avere una funzione che fa una divisione tra interi e
restituisce SIA il quoziente SIA il resto.
Come faresti ?
ah ... aggiungo di farlo senza creare una struct ad hoc che
incapsuli il doppio dato. Funzione che usi soltanto i tipi
nativi
Credo di essere riuscito a farlo ma senza l'uso dei puntatori :-((
==============================================
#include <iostream>
using namespace std;
void divisione (int a, int b, int& risdiv,int& resto)
{
  risdiv = a/b;
  resto = a%b;
  }
int main ()
{
  int risdiv=0;
  int resto=0;
 divisione(9,2,risdiv,resto);
 cout << "Risultato_div=" << risdiv << endl;
 cout << "Resto=" << resto << endl;
 return 0;
}
==========================================================
..con l'uso dei puntatori ho ottenuto degli errori ...appena possibile
riprovo, *adesso cerco di dormire, se ci riesco*...:-(((....
cmq, trovo molto interessante l'esrcizio che hai proposto.
Ho provato con i puntatori, ma, durante l'esecuzione del programma,
"Prova.exe ha smesso di funzionare. Si e' verificato un problema che
impedisce il finzionamento corretto del programma.Chiudere il
programma."
Lanciando il debug mi compare il seguente messaggio (Finestra Call
#0 004013A8 main() (C:\Users\programmi\Desktop\Prova\main.cpp:28)
===========================================
#include <iostream>
using namespace std;
void divisione (int a, int b, int* p1,int *p2 )
{
  int risdiv;
  int resto;
  p1=&risdiv;
  p2=&resto;
  risdiv = a/b;
  resto = a%b;
  }
int main ()
{
  int* p1=NULL ;
  int* p2=NULL ;
 divisione(9,2,p1,p2);
 cout << "Risultato_div=" << *p1 << endl;
 cout << "Resto=" << *p2 << endl;
 return 0;
}
===========================================
La linea 28 segnalata dalla finestra "Call stack", corrisponde
 cout << "Risultato_div=" << *p1 << endl;
....dove sbaglio e a cosa e' dovuto la segnalazione di errore che
ottengo?
Credo che l'errore sia dovuto al fatto che, nella funzione void
divisione:

p1=&risdiv;

p2=&resto;


sono due puntatori che fanno riferimento ad *indirizzi di variabili
locali*:

..il seguente programma sembra essere corretto:

========================================================

#include <iostream>
using namespace std;

void divisione (int a, int b, int* p1_risdiv,int *p2_resto )
{

*p1_risdiv= a/b;

*p2_resto= a%b;

p1_risdiv= NULL;

p2_resto= NULL;

}

int main ()
{

int risdiv=0;
int resto=0;

int* p1=NULL;
int* p2=NULL;

p1=&risdiv;
p2=&resto;

divisione(9,2,p1,p2);

cout << "Risultato_div=" << *p1 << endl;
cout << "Resto=" << *p2 << endl;

return 0;
}

===================================================

Cosa ne pensate?...esiste soluzione migliore?


Ciao e grazie mille!
Soviet_Mario
2013-04-14 11:08:42 UTC
Permalink
Il 14/04/2013 12:53, Osvald ha scritto:
CUT
Post by Osvald
Credo che l'errore sia dovuto al fatto che, nella funzione void
p1=&risdiv;
p2=&resto;
sono due puntatori che fanno riferimento ad *indirizzi di variabili
ma hai letto la risposta che ti ho dato ? Ci ho perso
mezz'ora ...

certo che è errato, ma non scatena nessun errore. Quello è
un errore logico, un'azione senza effetti al di fuori della
funzione. Il fault non nasce li
Post by Osvald
========================================================
#include<iostream>
using namespace std;
void divisione (int a, int b, int* p1_risdiv,int *p2_resto )
{
*p1_risdiv= a/b;
*p2_resto= a%b;
ok, almeno sin qui ci siamo
Post by Osvald
p1_risdiv= NULL;
p2_resto= NULL;
tutto questo invece di nuovo non serve a niente.
p1 e p2 in sé sono passati per valore (ossia il chiamante
COPIA due indirizzi nello stack frame del chiamato).
La funzione internamente può fare qualsiasi uso (anche
futile) di p1 e p2. E' solo dereferenziandoli, come fai
nelle prime due righe, che "esci" dallo scope locale e
raggiungi gli oggetti nello scope del chiamante.

quell'annullamento è ALMENO inutile, e potenzialmente nocivo
(ad es. se non fosse l'ultimo uso di p1 e p2, gli usi
successivi potrebbero scatenare condizioni di errore).
Non serve "sganciarli" esplicitamente, visto che sono solo
copie locali. Saranno distrutti all'uscita dalla funzione
Post by Osvald
}
int main ()
{
int risdiv=0;
int resto=0;
int* p1=NULL;
int* p2=NULL;
p1=&risdiv;
p2=&resto;
perchè non accorpare ?

int* p1=& risdiv;
int* p2=& resto;
Post by Osvald
divisione(9,2,p1,p2);
o perché non passare direttamente gli indirizzi (ossia
creando le variabili puntatore in modo temporaneo ? ...
tanto a te poi interessa il valore memorizzato nell'oggetto
puntato : è l'unica cosa permanente)

divisione(9, 2, & risdiv, & resto);

// questo CREA al volo due puntatori, che saranno copiati
nello stack frame di "divisione" come argomenti
Post by Osvald
cout<< "Risultato_div="<< *p1<< endl;
cout<< "Resto="<< *p2<< endl;
// e a quel punto faresti

cout<< "Risultato_div="<< risdiv << endl;
cout<< "Resto="<< resto << endl;

// p1 e p2 sono svaniti (ma dentro divisione vengono
ugualmente "visti" come argomenti passati)
Post by Osvald
return 0;
}
===================================================
Cosa ne pensate?...esiste soluzione migliore?
eliminare le variabili assolutamente inutili non è male, ma
in fin dei conti a serve solo capire come passare dentro e
fuori indirizzi e come usarli, quindi non è il momento di
"ottimizzare" ancora.
Post by Osvald
Ciao e grazie mille!
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Osvald
2013-04-14 13:22:45 UTC
Permalink
Post by Soviet_Mario
CUT
Post by Osvald
Credo che l'errore sia dovuto al fatto che, nella funzione void
p1=&risdiv;
p2=&resto;
sono due puntatori che fanno riferimento ad *indirizzi di variabili
ma hai letto la risposta che ti ho dato ? Ci ho perso
mezz'ora ...
La tua risposta e' arrivata in contemporanea al mio invio e non
l'avevo letta...cmq debbo leggere con piu' attenzione l'esempio che
hai fatto con double * CreaResultQuadrato .
Post by Soviet_Mario
certo che è errato, ma non scatena nessun errore. Quello è
un errore logico, un'azione senza effetti al di fuori della
funzione. Il fault non nasce li
OK!
Post by Soviet_Mario
Post by Osvald
========================================================
#include<iostream>
using namespace std;
void divisione (int a, int b, int* p1_risdiv,int *p2_resto )
{
   *p1_risdiv= a/b;
   *p2_resto= a%b;
ok, almeno sin qui ci siamo
Post by Osvald
   p1_risdiv= NULL;
   p2_resto= NULL;
tutto questo invece di nuovo non serve a niente.
p1 e p2 in sé sono passati per valore (ossia il chiamante
COPIA due indirizzi nello stack frame del chiamato).
La funzione internamente può fare qualsiasi uso (anche
futile) di p1 e p2. E' solo dereferenziandoli, come fai
nelle prime due righe, che "esci" dallo scope locale e
raggiungi gli oggetti nello scope del chiamante.
quell'annullamento è ALMENO inutile, e potenzialmente nocivo
(ad es. se non fosse l'ultimo uso di p1 e p2, gli usi
successivi potrebbero scatenare condizioni di errore).
Non serve "sganciarli" esplicitamente, visto che sono solo
copie locali. Saranno distrutti all'uscita dalla funzione
OK, avevo volutamente inserito quelle istruzioni proprio per notare
l'effetto sul programma chiamante.
Post by Soviet_Mario
Post by Osvald
   }
int main ()
{
    int risdiv=0;
    int resto=0;
    int* p1=NULL;
    int* p2=NULL;
    p1=&risdiv;
    p2=&resto;
perchè non accorpare ?
int* p1=& risdiv;
int* p2=& resto;
OK!
Post by Soviet_Mario
Post by Osvald
  divisione(9,2,p1,p2);
o perché non passare direttamente gli indirizzi (ossia
creando le variabili puntatore in modo temporaneo ? ...
tanto a te poi interessa il valore memorizzato nell'oggetto
puntato : è l'unica cosa permanente)
divisione(9, 2, & risdiv, & resto);
OK!
Post by Soviet_Mario
// questo CREA al volo due puntatori, che saranno copiati
nello stack frame di "divisione" come argomenti
Post by Osvald
  cout<<  "Risultato_div="<<  *p1<<  endl;
  cout<<  "Resto="<<  *p2<<  endl;
// e a quel punto faresti
cout<<  "Risultato_div="<<  risdiv <<  endl;
cout<<  "Resto="<<  resto <<  endl;
// p1 e p2 sono svaniti (ma dentro divisione vengono
ugualmente "visti" come argomenti passati)
Post by Osvald
  return 0;
}
===================================================
Cosa ne pensate?...esiste soluzione migliore?
eliminare le variabili assolutamente inutili non è male, ma
in fin dei conti a serve solo capire come passare dentro e
fuori indirizzi e come usarli, quindi non è il momento di
"ottimizzare" ancora.
.....pero', se ho ben capito, in base a quanto suggerisci, alla fine
siamo ritornati, *in linea di massima*, al primo programma che avevo
scritto, cio' senza l'uso *esplicito* dei puntatori*.

Ciao e grazie mille!
alexo
2013-04-14 15:40:42 UTC
Permalink
prova a pensare di avere una funzione che fa una divisione tra interi
e restituisce SIA il quoziente SIA il resto.
Come faresti ?
@Osvald: questo è uno dei modi per risolvere l'esercizio proposto.
Come vedi la funzione divisione restituisce alla funzione
chiamante il tipo void ma in pratica con l'uso dei puntatori essa
riesce a restituire due risultati. Questo è impossibile con
l'istruzione return che può restituire solo 1 valore. I puntatori
devono essere studiati e "digeriti" e per fare
questo occorre pazienza, impegno e tempo.

#include <iostream>

using std::cout;
using std::cin;
using std::endl;

void divisione(int, int, int*, int*);

int main()
{
int numeratore = 0;
int denominatore = 0;
int quoziente = 0;
int resto = 0;

cout << "Inerisci il numeratore della frazione: ";
cin >> numeratore;

cout << "Inerisci il denominatore della frazione: ";
cin >> denominatore;

divisione(numeratore, denominatore, &quoziente, &resto);

cout << "\nil risultato della divisione e\' " << quoziente
<< "\ncon il resto di " << resto << endl;

return 0;
}

void divisione(int num, int denom, int *risultato, int *resto)
{
*risultato = num / denom;
*resto = num % denom;
}
Osvald
2013-04-15 17:40:26 UTC
Permalink
Post by alexo
prova a pensare di avere una funzione che fa una divisione tra interi
e restituisce SIA il quoziente SIA il resto.
Come faresti ?
@Osvald: questo è uno dei modi per risolvere l'esercizio proposto.
Come vedi la funzione divisione restituisce alla funzione
chiamante il tipo void ma in pratica con l'uso dei puntatori essa
riesce a restituire due risultati. Questo è impossibile con
l'istruzione return che può restituire solo 1 valore. I puntatori
devono essere studiati e "digeriti" e per fare
questo occorre pazienza, impegno e tempo.
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void divisione(int, int, int*, int*);
int main()
{
     int numeratore = 0;
     int denominatore = 0;
     int quoziente = 0;
     int resto = 0;
     cout << "Inerisci il numeratore della frazione: ";
     cin >> numeratore;
     cout << "Inerisci il denominatore della frazione: ";
     cin >> denominatore;
     divisione(numeratore, denominatore, &quoziente, &resto);
     cout << "\nil risultato della divisione e\' " << quoziente
          << "\ncon il resto di " << resto << endl;
     return 0;
}
void divisione(int num, int denom, int *risultato, int *resto)
{
     *risultato = num / denom;
     *resto = num % denom;
}
OK...ti ringrazio..ho provato a risolvere l'esercizio con l'uso delle
variabili globali:

================================================

#include <iostream>
using namespace std;

int risdiv=0; //variabile globale
int resto=0; //variabile globale

void divisione (int a, int b)
{

risdiv = a/b;

resto = a%b;

}

int main ()
{

divisione(9,2);

cout << "Risultato_div=" << risdiv << endl;
cout << "Resto=" << resto << endl;

return 0;

}

==============================================

Sembra funzionare correttamente, pero', probabilmente, l'uso delle
variabili globali, e' da evitare (quando possibile) perche' possono
essere modificate da qualsiasi funzione presente nel programma con il
risultato che, forse, risulta piu' difficile individuare un errore
logico nel caso di un cattivo funzionamento del programma: giusto?

Inoltre , non saprei se a livello di impiego di memoria, con l'uso
delle variabili globali il programma e' meno ottimizzato rispetto ad
altre soluzioni.

Appena possibile provero' a risolvere l'esercizio anche usando le
strutture.

Ciao e grazie mille!!!
f***@gmail.com
2013-04-15 17:48:57 UTC
Permalink
Post by Osvald
Sembra funzionare correttamente, pero', probabilmente, l'uso delle
variabili globali, e' da evitare (quando possibile) perche' possono
essere modificate da qualsiasi funzione presente nel programma con il
risultato che, forse, risulta piu' difficile individuare un errore
logico nel caso di un cattivo funzionamento del programma: giusto?
Sì, le variabili globali hanno la fama di essere "il male™", per i motivi
che hai detto ma soprattuto perché in altri antichi linguaggi quasi tutte le
variabili lo erano - ed era impossibile capire cosa succedeva.
E' possibile scrivere qualsiasi programma senza utilizzarne neppure una ma,
anche qui, ci sono casi in cui sono utili (per chi vuole obiettare, penso ad
esempio ad una semplice alternativa al singleton).
Post by Osvald
Inoltre , non saprei se a livello di impiego di memoria, con l'uso
delle variabili globali il programma e' meno ottimizzato rispetto ad
altre soluzioni.
Dipende dal caso, ma direi uguale.
Post by Osvald
Appena possibile provero' a risolvere l'esercizio anche usando le
strutture.
Visto che stai studiando prova tutto quello che ti viene in mente! :-)
Post by Osvald
Ciao e grazie mille!!!
Ciao!
Osvald
2013-04-15 18:23:08 UTC
Permalink
Post by f***@gmail.com
Post by Osvald
Sembra funzionare correttamente, pero', probabilmente, l'uso delle
variabili globali, e' da evitare (quando possibile) perche' possono
essere modificate da qualsiasi funzione presente nel programma con il
risultato che, forse, risulta piu' difficile individuare un errore
logico nel caso di un cattivo funzionamento del programma: giusto?
Sì, le variabili globali hanno la fama di essere "il male™", per i motivi
che hai detto ma soprattuto perché in altri antichi linguaggi quasi tutte le
variabili lo erano - ed era impossibile capire cosa succedeva.
E' possibile scrivere qualsiasi programma senza utilizzarne neppure una ma,
anche qui, ci sono casi in cui sono utili (per chi vuole obiettare, penso ad
esempio ad una semplice alternativa al singleton).
Post by Osvald
Inoltre , non saprei se a livello di impiego di memoria, con l'uso
delle variabili globali il programma e' meno ottimizzato rispetto ad
altre soluzioni.
Dipende dal caso, ma direi uguale.
OK!
Post by f***@gmail.com
Post by Osvald
Appena possibile provero' a risolvere l'esercizio anche usando le
strutture.
Visto che stai studiando prova tutto quello che ti viene in mente! :-)
:-))

Quello che trovo impegnativo, oltre al linguaggio di programmazione
con le sue regole, i suoi costrutti...ecc....e' riuscire ad
individuare con una certa *rapidita'* quale e' *l'algoritmo* (che
credo, almeno per semplici problemi di programmazione, prescinde dal
linguaggio usato) per la soluzione (magari, inizialmente, anche non
ottimale) di un determinato problema.

Chiaramente ci sono degli algoritmi di base da imaparare: la ricerca
del max in un vettore, l'ordinamento di un vettore, merge di due
vettori, conversione di base..ecc....

Poi, chiaramente, per alcuni problemi di programmazione sono
richieste conoscenze di analisi matematica (es. calcolo approssimato
di un'equazione, di un integrale), ma, forse, in tal caso, avendo le
relative conoscenze, lo sviluppo dell'algoritmo risulta piu' semplice
rispetto ai predetti problemi.

Consigli a riguardo?

Ciao e grazie mille per la tempestivita' delle risposte!
Soviet_Mario
2013-04-15 18:37:06 UTC
Permalink
Post by Osvald
Post by f***@gmail.com
Post by Osvald
Sembra funzionare correttamente, pero', probabilmente, l'uso delle
variabili globali, e' da evitare (quando possibile) perche' possono
essere modificate da qualsiasi funzione presente nel programma con il
risultato che, forse, risulta piu' difficile individuare un errore
logico nel caso di un cattivo funzionamento del programma: giusto?
Sì, le variabili globali hanno la fama di essere "il male™", per i motivi
che hai detto ma soprattuto perché in altri antichi linguaggi quasi tutte le
variabili lo erano - ed era impossibile capire cosa succedeva.
E' possibile scrivere qualsiasi programma senza utilizzarne neppure una ma,
anche qui, ci sono casi in cui sono utili (per chi vuole obiettare, penso ad
esempio ad una semplice alternativa al singleton).
Post by Osvald
Inoltre , non saprei se a livello di impiego di memoria, con l'uso
delle variabili globali il programma e' meno ottimizzato rispetto ad
altre soluzioni.
Dipende dal caso, ma direi uguale.
OK!
Post by f***@gmail.com
Post by Osvald
Appena possibile provero' a risolvere l'esercizio anche usando le
strutture.
Visto che stai studiando prova tutto quello che ti viene in mente! :-)
:-))
Quello che trovo impegnativo, oltre al linguaggio di programmazione
con le sue regole, i suoi costrutti...ecc....e' riuscire ad
individuare con una certa *rapidita'* quale e' *l'algoritmo*
il C++ ti PERMETTE di scrivere codice estremamente
espressivo e leggibile, talvolta terso e compatto, ma non ti
costringe, e quindi ti permette anche di non farlo.
In questo certamente si presta facilmente ad essere usato in
modo pedestre.
Ad es. usi suicidi di macro ed operator overloading possono
portare ad apparenze paradossali e senza logica.
Un operator overloading malfatto può uccidere la leggibilità
del codice.
Anche un uso avanzato dei TEMPLATE annidati diventa
leggibile solo a gente che mangia e beve C++ da mattina a
sera. Se solo tenti di dare un occhiata alla libreria BOOST
templatica ti accorgi presto di faticare anche solo a
concepire cosa si sta dichiarando.
Associare la templatizzazione alle MACRO e ai caratteri di
preprocessamento tipo # e ## (token pasting) consente al
contempo di estendere in modo spaventoso la sinteticità, la
flessibilità, e l'ILLEGGIBILITA' del codice.
Quindi il codice di programmatori coi controcoglioni risulta
comprensibile solo ad altri coi controcoglioni.

Ad es. io ricordo anni fa quanta fatica facessi a leggere
degli esempi che postava allora un certo "kiuhnm", che
padroneggiava tutto questo a livelli veramente alti ed aveva
grande facilità ad astrarre e spremere tutto lo spremibile
da questo linguaggio. Certe cose non le ho nemmeno mai
capite più di tanto.
Post by Osvald
(che
credo, almeno per semplici problemi di programmazione, prescinde dal
linguaggio usato) per la soluzione (magari, inizialmente, anche non
ottimale) di un determinato problema.
si in generale è vero. Dipende quanto uno vuole spremere.
Lui ad es. era un fissato della computazione "statica" a
design time ! Praticamente tentava di rendere funzionale un
linguaggio più che altro "imperativo", anche con usi
spregiudicati della ricorsione statica.

E' vero che una parte della leggibilità è intrinseca
all'algoritmo, ma ogni linguaggio può lasciare la sua
impronta. E quella del C++ è molto variabile secondo lo
stile di chi lo usa, perché è molto flessibile e da poche
costrizioni.
Gli unici veri limiti che dava, almeno un tempo, erano nella
dinamicità e nell'introspezione, mentre era fortemente
estensibile proprio sul lato statico (credo, ma solo a naso,
non sia mai stato superato in questo da altri linguaggi).
Post by Osvald
Chiaramente ci sono degli algoritmi di base da imaparare: la ricerca
del max in un vettore, l'ordinamento di un vettore, merge di due
vettori, conversione di base..ecc....
Poi, chiaramente, per alcuni problemi di programmazione sono
richieste conoscenze di analisi matematica (es. calcolo approssimato
di un'equazione, di un integrale), ma, forse, in tal caso, avendo le
relative conoscenze, lo sviluppo dell'algoritmo risulta piu' semplice
rispetto ai predetti problemi.
Consigli a riguardo?
non ho capito del tutto la domanda ...
Post by Osvald
Ciao e grazie mille per la tempestivita' delle risposte!
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Osvald
2013-04-15 19:22:11 UTC
Permalink
[cut]
Post by Soviet_Mario
Post by Osvald
Chiaramente ci sono degli algoritmi di base da imaparare: la ricerca
del max in un vettore, l'ordinamento di un vettore, merge di due
vettori, conversione di base..ecc....
Poi,  chiaramente, per alcuni problemi di programmazione sono
richieste conoscenze di analisi matematica (es. calcolo approssimato
di un'equazione, di un integrale), ma, forse, in tal caso, avendo le
relative conoscenze, lo sviluppo dell'algoritmo risulta piu' semplice
rispetto ai predetti problemi.
Consigli a riguardo?
non ho capito del tutto la domanda ...
Es. Se mi si chiede di scrivere un programma per il calcolo di
un'equazione di secondo grado non ci sono molte difficolta', basta
conoscere la relativa formula risolutiva e scrivere un algoritmo e'
abbastanza semplice; in tal caso, basta avere delle conoscenze di base
di matematica.....ma se mi si chiede di scrivere un programma che
ordina un vettore di n elementi, oppure un merge di due vettori, non
ci vogliono grandi basi di matematica ma bisogna avere un buon
allenamento (almeno se si cerca di scriverlo senza sbirciare prima la
soluzione) con lo scrivere gli algortimi.

Spero di essere stato piu' chiaro.

Ciao e grazie mille!
f***@gmail.com
2013-04-15 19:28:40 UTC
Permalink
Post by Osvald
Quello che trovo impegnativo, oltre al linguaggio di programmazione
con le sue regole, i suoi costrutti...ecc....e' riuscire ad
individuare con una certa *rapidita'* quale e' *l'algoritmo* (che
credo, almeno per semplici problemi di programmazione, prescinde dal
linguaggio usato) per la soluzione (magari, inizialmente, anche non
ottimale) di un determinato problema.
Beh, questo è, in maniera concisa, il lavoro del programmatore.
Il vero lavoro non è conoscere un linguaggio, ma sapere quale algoritmo
conosciuto applicare o adattare, o scriverne uno ad-hoc.
Il linguaggio in se per se è solo un modo per esprimere quello che vuoi fare,
e se diventerai un programmatore vedrai che ne imparerai a decine, e farai
più o meno sempre le stesse cose :)
Post by Osvald
Chiaramente ci sono degli algoritmi di base da imaparare: la ricerca
del max in un vettore, l'ordinamento di un vettore, merge di due
vettori, conversione di base..ecc....
Poi, chiaramente, per alcuni problemi di programmazione sono
richieste conoscenze di analisi matematica (es. calcolo approssimato
di un'equazione, di un integrale), ma, forse, in tal caso, avendo le
relative conoscenze, lo sviluppo dell'algoritmo risulta piu' semplice
rispetto ai predetti problemi.
Consigli a riguardo?
Non saprei.. Credo questa sia una delle cose che dipende dall'esperienza..

Ti dico come faccio io, ma ognuno ha il suo modo di pensare..
I problemi di matematica/fisica sono i più immediati, basta applicare le
regole che usi a mano o, se non è accettabile, cercare in letteratura.
I problemi di ordinamento/ricerca/etc su strutture dati sono così comuni che
saltano subito all'occhio.
Se non ho la più pallida idea di cosa applicare perché è una situazione nuova
io faccio così, ma non è detto che sia la strada migliore: prima vedo se è
simile ad un problema NP, e in quel caso (almeno che non sia uno di quelli che
uso spesso) cerco in letteratura gli algoritmi più comuni; altrimenti, vedo
se è risolvibile con un divide-et-impera (in quel caso applichi qualche tipo
di ricerca binaria, a seconda dei casi) o, se ogni step è riconducibile al
precedente, se è più sensato un algoritmo greedy o una ricerca di un cammino
sul grafo equivalente.

Comunque, ribadisco, *questo* è il difficile e l'interessante del mondo della
programmazione: il linguaggio è solo un mezzo.

Ciao!
Osvald
2013-04-15 20:15:31 UTC
Permalink
Post by f***@gmail.com
Post by Osvald
Quello che trovo impegnativo, oltre al linguaggio di programmazione
con le sue regole, i suoi costrutti...ecc....e' riuscire ad
individuare con una certa *rapidita'* quale e' *l'algoritmo* (che
credo, almeno per semplici problemi di programmazione, prescinde dal
linguaggio usato) per la soluzione (magari, inizialmente, anche non
ottimale) di un determinato problema.
Beh, questo è, in maniera concisa, il lavoro del programmatore.
Il vero lavoro non è conoscere un linguaggio, ma sapere quale algoritmo
conosciuto applicare o adattare, o scriverne uno ad-hoc.
Il linguaggio in se per se è solo un modo per esprimere quello che vuoi fare,
e se diventerai un programmatore vedrai che ne imparerai a decine, e farai
più o meno sempre le stesse cose :)
OK!
Post by f***@gmail.com
Post by Osvald
Chiaramente ci sono degli algoritmi di base da imaparare: la ricerca
del max in un vettore, l'ordinamento di un vettore, merge di due
vettori, conversione di base..ecc....
Poi,  chiaramente, per alcuni problemi di programmazione sono
richieste conoscenze di analisi matematica (es. calcolo approssimato
di un'equazione, di un integrale), ma, forse, in tal caso, avendo le
relative conoscenze, lo sviluppo dell'algoritmo risulta piu' semplice
rispetto ai predetti problemi.
Consigli a riguardo?
Non saprei.. Credo questa sia una delle cose che dipende dall'esperienza..
Ti dico come faccio io, ma ognuno ha il suo modo di pensare..
I problemi di matematica/fisica sono i più immediati, basta applicare le
regole che usi a mano
[cut]

....esattamente, .intentevo proprio questo (vedi mia risposta a
Soviet_Mario), mentre problemi che non richiedono grandi conoscenze di
matematica, tipo il seguente::

http://www.dmi.unisa.it/people/nappi/www/lip/traccia1.pdf (e'
richiesto in C, sto provando a scriverlo in C++)

li trovo piu' impegnativi...cmq il prof. NON ha ancora spiegato il
tipo e difficolta' di programmi che chiedera' all'esame: spero NON
siano troppo complessi....non credo che con un corso di quattro mesi
si di venta un programmatore.

Ciao e grazie milleeeee
f***@gmail.com
2013-04-15 22:15:52 UTC
Permalink
Post by Osvald
Post by f***@gmail.com
Ti dico come faccio io, ma ognuno ha il suo modo di pensare..
I problemi di matematica/fisica sono i più immediati, basta applicare le
regole che usi a mano
[cut]
Post by f***@gmail.com
....esattamente, .intentevo proprio questo (vedi mia risposta a
Soviet_Mario), mentre problemi che non richiedono grandi conoscenze di
http://www.dmi.unisa.it/people/nappi/www/lip/traccia1.pdf (e'
richiesto in C, sto provando a scriverlo in C++)
li trovo piu' impegnativi...cmq il prof. NON ha ancora spiegato il
tipo e difficolta' di programmi che chiedera' all'esame: spero NON
siano troppo complessi....non credo che con un corso di quattro mesi
si di venta un programmatore.
Sì, il problema che hai postato richiede solo di pensarci un po', e vedrai
che verrai comunque giudicato sull'utilizzo del linguaggio, non sull'efficenza
del codice!
Sulla domanda iniziale e le risposte che ti ho dato, magari dovrai aspettare
di seguire corsi più in là (a ingegneria informatica, principalmente algoritmi
e strutture dati, ma molta roba mi ricordo la feci a elettronica digitale e
informatica 2 - fermo restando che il 90% di quello che uso oggi nel codice
l'ho imparato dai colleghi nei primi anni di lavoro, per cui non avere troppa
fretta!)

Ciao!

Soviet_Mario
2013-04-15 18:24:16 UTC
Permalink
CUT
Post by Osvald
OK...ti ringrazio..ho provato a risolvere l'esercizio con l'uso delle
domanda : PERCHE' lo hai fatto ?
Come ti hanno ricordato altri, globals are EVIL !
Ritarda l'apprendimento del loro uso oculato a quando ne
avrai realmente un bisogno stringente, e a quando avrai
veramente molto chiaro i concetti di scope (es. namespace) e
life-cycle.
Questo perché dovrai sempre usare il livello di
protezione-incapsulamento massimo compatibile con lo scopo,
e l'essere globale senza restrizioni è il più basso (in
realtà è assente).
Persino con le COSTANTI, le enum, roba che non ha effetti
collaterali stringenti, etc il global scope è male nel senso
che affolla lo spazio dei nomi disponibili in qualunque
scope, mentre il principio è che uno dovrebbe poter VEDERE
in un dato punto solo quel che è realmente necessario in
detto punto.
Certo : se scriverai roba matematica non dico di evitare di
"globalizzare" Pigreco o il Numero di Nepero, ma anche lì,
nel globalizzare è ancora più vitale che altrove darsi delle
convenzioni di denonimazione ordinate e significative.
Questo perché gli ausili mnemonici (come l'intellisense con
suo completamento automatico ad es. e ancor più funzioni di
inspecting della struttura complessiva delle dichiarazioni)
ti mostrano i nomi globali TUTTI insieme, e se ogni pezzo di
codice aggiunge il suo obolo, la lista lievita e diventa
poco efficace usare questi ausili imho comodissimi.
Imho come termometro di un programma mal strutturato
potresti quasi pari pari valutare con che efficacia si usano
questi ausili : se li trovi inutili, la struttura è piatta o
eccessivamente annidata oltre il necessario.
Post by Osvald
================================================
#include<iostream>
using namespace std;
int risdiv=0; //variabile globale
int resto=0; //variabile globale
void divisione (int a, int b)
{
risdiv = a/b;
resto = a%b;
}
int main ()
{
divisione(9,2);
cout<< "Risultato_div="<< risdiv<< endl;
cout<< "Resto="<< resto<< endl;
return 0;
}
==============================================
Sembra funzionare correttamente, pero', probabilmente, l'uso delle
variabili globali, e' da evitare (quando possibile) perche' possono
essere modificate da qualsiasi funzione presente nel programma con il
risultato che, forse, risulta piu' difficile individuare un errore
fosse solo la difficoltà di debug.
Il fatto che ti cambia proprio il genere di codice che
scrivi. Scrivi un codice molto più breve ma anche irto di
interconnessioni ed interdipendenze tra unità funzionali
spesso in realtà indipendenti.
Ogni volta che ritocchi un pezzo di codice dove viene usato
un globale, ti devi poi chiedere se e in che misura questo
influenzerà tutte le altre parti di programma dove lo stesso
globale (o altri a loro volta interconnessi) vengono usati.
L'incapsulamento dei dati crolla miseramente, e con esso la
manutenibilità. Un codice chiaro è quello in cui capisci
cosa sta succedendo leggendo solo il corpo della funzione
che stai visualizzando, non uno in cui continuamente devi
saltare ovunque perché mancano informazioni locali e ci sono
rimandi
Post by Osvald
logico nel caso di un cattivo funzionamento del programma: giusto?
più di quel che percepisci ora, si
Post by Osvald
Inoltre , non saprei se a livello di impiego di memoria, con l'uso
delle variabili globali il programma e' meno ottimizzato rispetto ad
altre soluzioni.
tutt'altro. Almeno in quanto a COMPATTEZZA è spesso più
ottimizzato. MA è uno di quei casi in cui il rapporto tra
vantaggi e svantaggi è totalmente negativo, se intendi una
strategia generale.
Ci sono pure eccezioni, ma a un certo punto lo sentirai
naturale capire quando si verificano. E come filosofia
generale le costanti possono tendere a galleggiare su di
scope normalmente più delle variabili.

Altra cosa : scrivere codice "thread safe" in presenza di
globaloni è praticamente impossibile o estremamente
inefficiente (dovendo inserire codici "bloccanti" di mero
sincronizzamento o attributi inefficientizzanti tipo
"volatile" per la ram, che flushano/ricaricano sempre i
registri alle/dalle rispettive locazioni di memoria globale,
in ambito NON thread safe).

Aggiungo che io non so programmare multi thread (cosa
sicuramente preziosa per certi programmi specie sui
processori di oggi multicore fisici), tuttavia una parziale
consapevolezza di un certo stile è necessario almeno per
evitarlo e non incapparci senza volere :-) Perché se ci
incappi senza saperlo, è chiaro che poi incontri
problematiche che appaiono misteriose (variabili controllate
che mutano per magia) e solo lacrime e sangue di debugging
possono scoprire.
Post by Osvald
Appena possibile provero' a risolvere l'esercizio anche usando le
strutture.
mah ... trova contesti adatti alle strutture. Se un
esercizio è forzato e innaturale, imho non è manco tanto
utile. Apprezzi una cosa solo quando ti semplifica.

Che so, prova a pensare a una rubrica senza strutture, o a
una rappresentazione di punti tridimensionali con array
lisci o array di appropriate strutture, e poi vedi l'aspetto
dei codici alternativi con e senza.
Se invece usi una caratteristica a sproposito, non la
apprezzi più di tanto.
Post by Osvald
Ciao e grazie mille!!!
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Manlio Perillo
2013-04-15 20:17:55 UTC
Permalink
prova a pensare di avere una funzione che fa una divisione tra interi e
restituisce SIA il quoziente SIA il resto. Come faresti ?
div_t d = div(13, 3);
[...]
Ciao Manlio
enoquick
2013-04-13 22:51:04 UTC
Permalink
Post by Osvald
[cut]
Post by enoquick
Post by Osvald
Post by enoquick
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
OK...puoi, fare qualche esempio *semplice* (*se possibile*) di
convenienza dell'uso dei puntatori senza l'impiego della memoria
dinamica?
Ciao e grazie milleeeeeee!
void f(const T&)


Il primo parametro è un reference ma in pratica è un puntatore


Oppure


void f(T* x)


Oppure

int a;int b;
int* x = expr ? &a : &b

......

uso di x



Ma,sinceramente, non mi è mai capitato in pratica di usare direttamente
un puntatore ad una variabile sullo stack (l' ultimo caso)
Se qualcuno ha qualche altra idea è ben accetto
Soviet_Mario
2013-04-14 00:14:31 UTC
Permalink
Post by enoquick
Post by Osvald
[cut]
Post by enoquick
Post by Osvald
Post by enoquick
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
OK...puoi, fare qualche esempio *semplice* (*se possibile*) di
convenienza dell'uso dei puntatori senza l'impiego della memoria
dinamica?
Ciao e grazie milleeeeeee!
void f(const T&)
Il primo parametro è un reference ma in pratica è un puntatore
Oppure
void f(T* x)
Oppure
int a;int b;
int* x = expr ? &a : &b
.......
uso di x
Ma,sinceramente, non mi è mai capitato in pratica di usare direttamente
un puntatore ad una variabile sullo stack (l' ultimo caso)
Se qualcuno ha qualche altra idea è ben accetto
beh, tutte le volte che una funzione deve ritornare più di
un unico risultato, è inevitabile passare reference e/o
puntatori (secondo i gusti, i secondi sono più espliciti
imho). E i parametri passati alla funzione, possono e spesso
sono anche variabili automatiche (o a propria volta
parametri ricevuti, ammettendo una certa catena di chiamate).


P.S. no, non sapevo che new "placement" fosse stato
estromesso, perché non conosco lo standard.
Devo dire che lo trovato molto comodo e garantista, e
veramente non ne comprendo la ragione.
Era uno dei modi di avere garanzie minime certe di memoria
(preallocazione statica), da gestire però in modo dinamico
nel senso di riciclabile per oggetti diversi. Non so come
mai sia stato tolto. Forse qualche nuova funzionalità
permette le stesse cose in modo più agile ? O forse la
memoria non è ormai più considerata una risorsa men che
sicura, vista l'abbondanza ? Boh
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
enoquick
2013-04-14 00:34:19 UTC
Permalink
Post by enoquick
Post by Osvald
[cut]
Post by enoquick
Post by Osvald
Post by enoquick
Puntatori e memoria dinamica (heap) non sono la stessa cosa
1) quando è più utile usare i puntatori
2) quando è più utile usare la memoria dinamica
Se ho ben capito, con i puntatori si ha *anche* la possibilità di
http://www.cplusplus.com/doc/tutorial/dynamic/
potrebbe essere un caso in cui conviene utilizzare i puntatori e la
memoria dinamica; infatti, nell'esempio, la dimensione dell' array
viene stabilita in fase di runtime (mediante input dell'utente) e si
ha quindi la possibilità di avere un array a dimensione variabile e
dipendente dall'input dell'utente.
Infatti; per usare la memoria dinamica è obbligatorio l' uso dei
puntatori ma l'uso dei puntatori non implica necessariamente l'uso
della memoria dinamica
OK...puoi, fare qualche esempio *semplice* (*se possibile*) di
convenienza dell'uso dei puntatori senza l'impiego della memoria
dinamica?
Ciao e grazie milleeeeeee!
void f(const T&)
Il primo parametro è un reference ma in pratica è un puntatore
Oppure
void f(T* x)
Oppure
int a;int b;
int* x = expr ? &a : &b
.......
uso di x
Ma,sinceramente, non mi è mai capitato in pratica di usare direttamente
un puntatore ad una variabile sullo stack (l' ultimo caso)
Se qualcuno ha qualche altra idea è ben accetto
beh, tutte le volte che una funzione deve ritornare più di un unico
risultato, è inevitabile passare reference e/o puntatori (secondo i
gusti, i secondi sono più espliciti imho). E i parametri passati alla
funzione, possono e spesso sono anche variabili automatiche (o a propria
volta parametri ricevuti, ammettendo una certa catena di chiamate).
Si, è la simmetria di f(T*)
Ma parlavo di 'usare direttamente un puntatore ad una variabile sullo stack'
tipo :
int a;int b;
int* x = expr ? &a : &b
...
uso di x
P.S. no, non sapevo che new "placement" fosse stato estromesso, perché
non conosco lo standard.
Devo dire che lo trovato molto comodo e garantista, e veramente non ne
comprendo la ragione.
Era uno dei modi di avere garanzie minime certe di memoria
(preallocazione statica), da gestire però in modo dinamico nel senso di
riciclabile per oggetti diversi. Non so come mai sia stato tolto. Forse
qualche nuova funzionalità permette le stesse cose in modo più agile ? O
forse la memoria non è ormai più considerata una risorsa men che sicura,
vista l'abbondanza ? Boh
La mia era una domanda, non so se il new "placement" è stato tolto
Dovrei mettermi a cercare per saperlo
Soviet_Mario
2013-04-13 15:28:23 UTC
Permalink
Post by enoquick
Post by Osvald
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
======================================
// Scambio di due variabili di tipo intero
#include <iostream>
using namespace std;
int main()
{
int x=10,y=20;
int* p_x=NULL;
p_x=new int;
*p_x=x;
x=y;
y=*p_x;
delete p_x;
cout<<"x="<<x<<endl<<"y="<<y;
return 0;
}
===============================
Con i puntatori, se ho ben capito, è possibile, un uso dinamico della
memoria; e' possibile cioe', allocare e deallocare spazi di memoria
(memoria heap);
se nel predetto programma NON avessi usato il puntatore, ma una
semplice variabile di appoggio(utilizzo memoria stack) di tipo intero
(per eseguire lo scambio delle varabili intere x e y), il programma
sarebbe stato meno ottimizzato dal punto di vista dell'impiego di
memoria?
Ciao e grazie milleeeeee!
Fra stack e heap i costi di accesso sono uguali
mmm, avrei pensato che dipendesse dal codice di basso
livello prodotto.

Ad es. sul mio vecchio sistema (non parlo di visual studio
di cui non ho mai prodotto l'assembler intermedio per
visionarlo), le variabili esterne e la memoria heap venivano
indirizzate con istruzioni con più cicli di clock che non le
variabili accessite (o accedute ?? :-)) tramite registri
puntatori precaricati (tipo BP, SP) o con indirizzi const.
Ovviamente sono cmq quisquiglie che possono diventare
significative forse per array annidati letti e riscritti
molte volte, mentre l'osservazione che fai tu ha certamente
una validità più generale e più significativa in senso
quantitativo.
Post by enoquick
La differenza sta che new (o malloc in C) ha un costo ben superiore all'
allocazione di una variabile nello stack e per simmetria anche delete (o
free in C)
P.S. che voi sappiate, con gli ultimi standard, ci sono modi
di interrogare lo heap manager per conoscere tipo quanta
memoria libera rileva, stato di frammentazione, ed
eventualmente forzare a mano le operazioni di compattazione
e via discorrendo ? Nelle antiche librerie borland c'erano
funzioni di inspecting tipo heapwalk, heapchecknode e così via.
O rimangono totalmente trasparenti.

Ah ... per l'OP, a proposito di uso EFFICIENTE della memoria
a cui faceva riferimento.
Qualora dovesse diventare veramente necessario e critico
allocare e deallocare piccoli blocchetti, si può anche fare
l'overload di NEW/DELETE, usando il cosiddetto "new
placement" (o almeno si poteva, ormai parlo solo al
passato), in cui praticamente il new si limitava a ripartire
spazi di memoria PREALLOCATA, spesso statica, bypassando il
memory manager per una gestione manuale.
Questo ha senso se ad es. si deve scrivere un allocatore
molto specifico, tipo che produce chunk di dimensione
costante, e che quindi non ha necessità di tenere traccia
della dimensione stessa.

Ho un po' di ruggine, ma l'OP potrebbe guardare, in seguito,
per il momento mi pare prematuro, NEW PLACEMENT

ciao
cCCP
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Manlio Perillo
2013-04-13 16:44:09 UTC
Permalink
[...]
Post by enoquick
Fra stack e heap i costi di accesso sono uguali
mmm, avrei pensato che dipendesse dal codice di basso livello prodotto.
Ad es. sul mio vecchio sistema (non parlo di visual studio di cui non ho
mai prodotto l'assembler intermedio per visionarlo), le variabili
esterne e la memoria heap venivano indirizzate con istruzioni con più
cicli di clock che non le variabili accessite (o accedute ?? :-))
tramite registri puntatori precaricati (tipo BP, SP) o con indirizzi
const.
Posta il codice che avevi scritto.
In linea di massima, utilizzando i puntatori hai un problema di aliasing,
che impedisce al compilatore di ottimizzare il codice (per maggiori
informazioni cerca dei tutorial sulla keyword restrict di C99).
[...]
P.S. che voi sappiate, con gli ultimi standard, ci sono modi di
interrogare lo heap manager per conoscere tipo quanta memoria libera
rileva, stato di frammentazione, ed eventualmente forzare a mano le
operazioni di compattazione e via discorrendo ?
No, e mai ci saranno.
Forse quando il C++ supporterà il garbage collecting, ma non è detto.
[...]
Ciao Manlio
Soviet_Mario
2013-04-13 20:28:03 UTC
Permalink
Post by Manlio Perillo
[...]
Post by enoquick
Fra stack e heap i costi di accesso sono uguali
mmm, avrei pensato che dipendesse dal codice di basso livello prodotto.
Ad es. sul mio vecchio sistema (non parlo di visual studio di cui non ho
mai prodotto l'assembler intermedio per visionarlo), le variabili
esterne e la memoria heap venivano indirizzate con istruzioni con più
cicli di clock che non le variabili accessite (o accedute ?? :-))
tramite registri puntatori precaricati (tipo BP, SP) o con indirizzi
const.
Posta il codice che avevi scritto.
ah boh, dovrei recuperare roba compilata col borland 2.0 per
dos :-)

in ogni caso ricordo reference compilate come

mov _AX, [varptr nomevar]

per i globaloni

etc

mentre per i parametri funzione roba tipo

mov _AX, [_BP + const_offset]

mov [_SP + 3], _BX;

nel primo caso si hanno in realtà due accessi alla memoria :
ad una variabile per nome, leggendo il contenuto, e poi
usando tale valore per indirizzare e leggere di nuovo la ram

nell'altro caso si usava un valore di registro puntatore (BP
era usato per i parametri locali o SP, non ricordo con
precisione, e manco se gli offset negativi erano per le
automatiche o quelli positivi, mi pare la seconda, cmq erano
costanti inline, quindi cablati nel macchina e non da
leggere nella memoria) precaricato, e un solo accesso alla ram.


Tra l'altro, vado parzialmente OT per questa branca ma,
penso, IT col post iniziale sull'efficienza :

Lo stack ha anche una ulteriore garanzia implicita (mi pare
su qualsiasi architettura) : è sempre memoria contigua non
frammentata e non sparsa qua e là, quindi credo che non sia
mai penalizzato da costi variabili di eventuale paginazione
e scherzetti di memoria virtuale, swap etc etc.

Non saprei se la stessa garanzia possa esistere per lo
"heap", in teoria un programma che alloca moltissimo, e usa
la memoria in certi modi, potrebbe vedere swappati dei
blocchi usati di rado. Tutto ciò è trasparente al codice, ma
dietro le quinte è probabile che ci sia un memory manager
dell'OS che gestisce la memoria fisica interponendosi al
programma utente di normale layer.
Post by Manlio Perillo
In linea di massima, utilizzando i puntatori hai un problema di aliasing,
mi chiariresti cosa si intende per aliasing in questo
contesto ? E' un nome che associo, a torto, a effetti della
grafica e della granularità
Post by Manlio Perillo
che impedisce al compilatore di ottimizzare il codice (per maggiori
informazioni cerca dei tutorial sulla keyword restrict di C99).
[...]
P.S. che voi sappiate, con gli ultimi standard, ci sono modi di
interrogare lo heap manager per conoscere tipo quanta memoria libera
rileva, stato di frammentazione, ed eventualmente forzare a mano le
operazioni di compattazione e via discorrendo ?
No, e mai ci saranno.
in effetti a ben vedere nemmeno servono, se si acquisiscono
le risorse coi costruttori
Post by Manlio Perillo
Forse quando il C++ supporterà il garbage collecting, ma non è detto.
uhm, avrei detto il contrario. Ossia che il GC nasce apposta
per non volersi occupare più di nulla a manina.
Certo, un qualche modo di forzare il committing ci sarebbe
pure, ma troppe ingerenze sugli internals è un po' l'opposto
della (perfida !) filosofia del GC.

Personalmente ho una specie di intolleranza al C#, ad es.
Mi sembra di usare un linguaggio difficile come il C++ ma
con le storture del visual basic :)
Post by Manlio Perillo
[...]
Ciao Manlio
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Manlio Perillo
2013-04-14 16:44:03 UTC
Permalink
[...]
Post by Manlio Perillo
In linea di massima, utilizzando i puntatori hai un problema di aliasing,
mi chiariresti cosa si intende per aliasing in questo contesto ? E' un
nome che associo, a torto, a effetti della grafica e della granularità
http://en.wikipedia.org/wiki/Restrict

Ma fa riferimento ad un problema causato dall'uso dei puntatori, e non
dall'uso dell'heap contro lo stack.
[...]
Ciao Manlio
Soviet_Mario
2013-04-14 19:51:42 UTC
Permalink
Post by Manlio Perillo
[...]
Post by Manlio Perillo
In linea di massima, utilizzando i puntatori hai un problema di aliasing,
mi chiariresti cosa si intende per aliasing in questo contesto ? E' un
nome che associo, a torto, a effetti della grafica e della granularità
http://en.wikipedia.org/wiki/Restrict
ti ringrazio, adesso vado a leggermi la pagina
ciao
CCCP
Post by Manlio Perillo
Ma fa riferimento ad un problema causato dall'uso dei puntatori, e non
dall'uso dell'heap contro lo stack.
[...]
Ciao Manlio
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Soviet_Mario
2013-04-14 19:58:23 UTC
Permalink
Post by Manlio Perillo
[...]
Post by Manlio Perillo
In linea di massima, utilizzando i puntatori hai un problema di aliasing,
mi chiariresti cosa si intende per aliasing in questo contesto ? E' un
nome che associo, a torto, a effetti della grafica e della granularità
http://en.wikipedia.org/wiki/Restrict
interessante ! Non avevo mai considerato questo problema.
In effetti la parola chiave "restrict" mi sembra in certa
misura speculare a "volatile" (se esiste ancora); nel senso
che con la prima garantisci che sia lecito al compilatore
fare assunzioni ottimizzanti, mentre con la seconda gli
ordini espressamente di non fare mai assunzioni (e
ricaricare sempre da o scrivere sempre in ram).
ciao
CCCP
Post by Manlio Perillo
Ma fa riferimento ad un problema causato dall'uso dei puntatori, e non
dall'uso dell'heap contro lo stack.
[...]
Ciao Manlio
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
neonano
2013-04-13 22:14:17 UTC
Permalink
... le variabili esterne e la memoria heap venivano
indirizzate con istruzioni con più cicli di clock che non le
variabili accessite (o accedute ?? :-)) tramite registri
puntatori precaricati (tipo BP, SP) o con indirizzi const.
Come dicevo nel post precedente, BP e SP sono il mezzo
che i processori 8086 ereditavano dall' 8080/8085 e '8008
per gestire lo stack. altri processori avevano altri registri e
istruzioni e modi di indirizzamento ma tutto somato, avevano
dei modi efficienti per gestire uno stack.
Non però una heap purtroppo.
Ovviamente sono cmq quisquiglie che possono diventare
significative forse per array annidati letti e riscritti
molte volte,
...
Perciò io dico: "... *generalmente* sono comparabili."
enoquick
2013-04-13 22:37:29 UTC
Permalink
Post by enoquick
Post by Osvald
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
======================================
// Scambio di due variabili di tipo intero
#include <iostream>
using namespace std;
int main()
{
int x=10,y=20;
int* p_x=NULL;
p_x=new int;
*p_x=x;
x=y;
y=*p_x;
delete p_x;
cout<<"x="<<x<<endl<<"y="<<y;
return 0;
}
===============================
Con i puntatori, se ho ben capito, è possibile, un uso dinamico della
memoria; e' possibile cioe', allocare e deallocare spazi di memoria
(memoria heap);
se nel predetto programma NON avessi usato il puntatore, ma una
semplice variabile di appoggio(utilizzo memoria stack) di tipo intero
(per eseguire lo scambio delle varabili intere x e y), il programma
sarebbe stato meno ottimizzato dal punto di vista dell'impiego di
memoria?
Ciao e grazie milleeeeee!
Fra stack e heap i costi di accesso sono uguali
mmm, avrei pensato che dipendesse dal codice di basso livello prodotto.
Ad es. sul mio vecchio sistema (non parlo di visual studio di cui non ho
mai prodotto l'assembler intermedio per visionarlo), le variabili
esterne e la memoria heap venivano indirizzate con istruzioni con più
cicli di clock che non le variabili accessite (o accedute ?? :-))
tramite registri puntatori precaricati (tipo BP, SP) o con indirizzi const.
Ovviamente sono cmq quisquiglie che possono diventare significative
forse per array annidati letti e riscritti molte volte, mentre
l'osservazione che fai tu ha certamente una validità più generale e più
significativa in senso quantitativo.
Diciamo che stai facendo un pò il pignolo

Le new/malloc e la controparte delete/free sono alquante costose su
tutte le architetture ma l' accesso tramite puntatore che punta ad una
variabile sullo stack o ad un indirizzo allocato nella memoria dinamica
è praticamente lo stesso,almeno sulle architetture ad indirizzamento piatto

Volendo essere pignoli si può dire che il compilatore potrebbe
ottimizzare l' accesso tramite puntatore ad una variabile sullo stack
usando come base il registro dello stack pointer ed in memoria tenersi
solo lo spiazzamento rispetto allo stack, oppure meglio ancora tenersi
l' indirizzo in un registro (ma questo vale anche per un puntatore che
punta alla memoria dinamica)
P.S. che voi sappiate, con gli ultimi standard, ci sono modi di
interrogare lo heap manager per conoscere tipo quanta memoria libera
rileva, stato di frammentazione, ed eventualmente forzare a mano le
operazioni di compattazione e via discorrendo ? Nelle antiche librerie
borland c'erano funzioni di inspecting tipo heapwalk, heapchecknode e
così via.
O rimangono totalmente trasparenti.
Per quello che so non mi risulta niente di tutto ciò
Se vuoi controllare queste cose ti costruisci un allocatore
Ah ... per l'OP, a proposito di uso EFFICIENTE della memoria a cui
faceva riferimento.
Qualora dovesse diventare veramente necessario e critico allocare e
deallocare piccoli blocchetti, si può anche fare l'overload di
NEW/DELETE, usando il cosiddetto "new placement" (o almeno si poteva,
ormai parlo solo al passato), in cui praticamente il new si limitava a
ripartire spazi di memoria PREALLOCATA, spesso statica, bypassando il
memory manager per una gestione manuale.
Questo ha senso se ad es. si deve scrivere un allocatore molto
specifico, tipo che produce chunk di dimensione costante, e che quindi
non ha necessità di tenere traccia della dimensione stessa.
Ho un po' di ruggine, ma l'OP potrebbe guardare, in seguito, per il
momento mi pare prematuro, NEW PLACEMENT
E' ancora possibile per una data classe ridefinire i metodi statici new
e delete
Ma il new placement è stato tolto dallo standard ?
neonano
2013-04-13 21:50:56 UTC
Permalink
Post by enoquick
Fra stack e heap i costi di accesso sono uguali
Io andrei cauto col fare affermazioni troppo drastiche. In generale dipende
da come sono implementati lo stack e la heap, quindi dal compilatore e
dalle librerie, ma soprattutto dall'hardware a disposizione.

Quindi io direi: in generale il costi di acccesso sono comparabili ma
dipende dal caso specifico.
Post by enoquick
La differenza sta che new (o malloc in C) ha un costo ben superiore all'
allocazione di una variabile nello stack e per simmetria anche delete (o
free in C)
Questa affermazione è condivisibile ma anche qui andrei cauto.
Prima di tutto la gestione di uno stack è più semplice solo perché
l'hardware, il linguaggio macchina, il processore, la MMU mettono
a disposizione mezzi per gestire lo stack molto efficientemente ma
la cosa dipende ancora dal caso particolare.

Viceversa non è tanto vero che gestire una heap è meno efficiente
che gestire uno stack, solo chla heap porta facilmente a memory
leak e in genere le contromisure sono costose o inefficienti.
enoquick
2013-04-13 22:41:41 UTC
Permalink
Post by neonano
Post by enoquick
Fra stack e heap i costi di accesso sono uguali
Io andrei cauto col fare affermazioni troppo drastiche. In generale dipende
da come sono implementati lo stack e la heap, quindi dal compilatore e
dalle librerie, ma soprattutto dall'hardware a disposizione.
Ovviamente, o già risposto a questo ma si tratta di pignoleria
Post by neonano
Quindi io direi: in generale il costi di acccesso sono comparabili ma
dipende dal caso specifico.
Post by enoquick
La differenza sta che new (o malloc in C) ha un costo ben superiore all'
allocazione di una variabile nello stack e per simmetria anche delete (o
free in C)
Questa affermazione è condivisibile ma anche qui andrei cauto.
Prima di tutto la gestione di uno stack è più semplice solo perché
l'hardware, il linguaggio macchina, il processore, la MMU mettono
a disposizione mezzi per gestire lo stack molto efficientemente ma
la cosa dipende ancora dal caso particolare.
Sulle architetture comuni il costo di new/delete è sempre alto in quanto
occorre sotto un esse un gestore della memoria
Post by neonano
Viceversa non è tanto vero che gestire una heap è meno efficiente
che gestire uno stack, solo chla heap porta facilmente a memory
leak e in genere le contromisure sono costose o inefficienti.
Questo non l'ho mai detto
Luca Risolia
2013-04-14 10:07:35 UTC
Permalink
Post by Osvald
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
======================================
// Scambio di due variabili di tipo intero
#include <iostream>
using namespace std;
int main()
{
int x=10,y=20;
int* p_x=NULL;
Usa nullptr per i puntatori, non NULL.
http://www.stroustrup.com/C++11FAQ.html#nullptr
Osvald
2013-04-14 11:00:42 UTC
Permalink
Post by Osvald
Sto provando ad assegnarmi qualche esercizio sui puntatori, ad es. il
seguente programma, esegue lo scambio tra due variabili mediante l'uso
======================================
// Scambio di due variabili di tipo intero
#include <iostream>
using namespace std;
int main()
{
int x=10,y=20;
int* p_x=NULL;
Usa nullptr per i puntatori, non NULL.http://www.stroustrup.com/C++11FAQ.html#nullptr
Utilizzando nullptr ottengo l'errore:

"C:\Users\cesare\Desktop\programmi\main.cpp|24|warning: identifier
'nullptr' is a keyword in C++11 [-Wc++0x-compat]|"

...probabilmente il copmilatore che utilizzo (Code Blocks::con
compilatore: gnu gcc) NON e' aggiornato alla vers. C++11?

Ciao e grazie mille!
Luca Risolia
2013-04-14 11:41:01 UTC
Permalink
Post by Osvald
Post by Osvald
int* p_x=NULL;
Usa nullptr per i puntatori, non NULL.http://www.stroustrup.com/C++11FAQ.html#nullptr
"C:\Users\cesare\Desktop\programmi\main.cpp|24|warning: identifier
'nullptr' is a keyword in C++11 [-Wc++0x-compat]|"
...probabilmente il copmilatore che utilizzo (Code Blocks::con
compilatore: gnu gcc) NON e' aggiornato alla vers. C++11?
Credo il tuo compilatore ti suggerisca di abilitare C++11 tramite
l'opzione -Wc++0x-compat
Luca Risolia
2013-04-14 11:43:16 UTC
Permalink
Post by Luca Risolia
Post by Osvald
Post by Luca Risolia
Post by Osvald
int* p_x=NULL;
Usa nullptr per i puntatori, non
NULL.http://www.stroustrup.com/C++11FAQ.html#nullptr
"C:\Users\cesare\Desktop\programmi\main.cpp|24|warning: identifier
'nullptr' is a keyword in C++11 [-Wc++0x-compat]|"
...probabilmente il copmilatore che utilizzo (Code Blocks::con
compilatore: gnu gcc) NON e' aggiornato alla vers. C++11?
Credo il tuo compilatore ti suggerisca di abilitare C++11 tramite
l'opzione -Wc++0x-compat
No, scusa, non avevo letto bene. Quel -Wc++0x-compat è per
abilitare/disabilitare il warning. Per abilitare C++11 passa -std=c++0x
al compilatore.
Osvald
2013-04-14 13:07:25 UTC
Permalink
Post by Luca Risolia
Post by Luca Risolia
Post by Osvald
Post by Luca Risolia
Post by Osvald
int* p_x=NULL;
Usa nullptr per i puntatori, non
NULL.http://www.stroustrup.com/C++11FAQ.html#nullptr
"C:\Users\cesare\Desktop\programmi\main.cpp|24|warning: identifier
'nullptr' is a keyword in C++11 [-Wc++0x-compat]|"
...probabilmente il copmilatore che utilizzo (Code Blocks::con
compilatore: gnu gcc) NON e' aggiornato alla vers. C++11?
Credo il tuo compilatore ti suggerisca di abilitare C++11 tramite
l'opzione -Wc++0x-compat
No, scusa, non avevo letto bene. Quel -Wc++0x-compat è per
abilitare/disabilitare il warning. Per abilitare C++11 passa -std=c++0x
al compilatore.
Nella scheda compiler flags del compilatore trovo, tra le varie
opzioni:

-std=c++0x

-std=c++11

...ho notato che, se scelgo la prima che hai suggerito o la seconda
non ottengo errori anche se non conosco la diffferenza trale le due
opzioni.


Ciao e grazie mille!
Luca Risolia
2013-04-14 13:37:33 UTC
Permalink
Post by Osvald
Nella scheda compiler flags del compilatore trovo, tra le varie
-std=c++0x
-std=c++11
...ho notato che, se scelgo la prima che hai suggerito o la seconda
non ottengo errori anche se non conosco la diffferenza trale le due
opzioni.
Nessuna differenza.
Continua a leggere su narkive:
Loading...