Newsgroup: it.comp.lang.c++
Titolo: Stranezze di VC++?

Cari amici vi sottopongo una stranezza di VC++ 6.0 di cui
mi sono reso conto in seguito ad una richiesta.
Se eliminate il copy ctor otterrete un output diverso (indipendentemente
dalle ottimizzazioni), in sostanza VC++ non e` capace di eliminare una
chiamata al copy ctor (come mi pare essere consentito dal linguaggio)
quando utilizza il copy ctor di default.
Il Borland C++ 5.02 invece ottimizza entrambi i casi.
A voi la parola...
Paolo
#include <iostream>
using namespace std;
class MyClass {
  public:
    MyClass(const char* p=0) : m_p(p) {
      cout << "C ";
      if (p) cout << p;
      cout << endl;
    }
    MyClass(const MyClass& cl) : m_p(0) { cout << "CC" << endl;}
    ~MyClass(){
      cout << "D ";
      if (m_p) cout << m_p;
      cout << endl;
    }
  private:
    const char* m_p;
};
void foo2(MyClass cl_) {
 cout << "Foo2" << endl;
}
MyClass foo1(void) {
  MyClass cl("cl");
  cout << "exiting foo1" << endl;
  return cl;
}
int main(int argc,char *argv[]) {
  foo2(foo1());
  char c;
  cin >> c;
  return 0;
}
--------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
--------------------------------------------------

 Il Borland C++ 5.02 invece ottimizza entrambi i casi.
Mi sembra di capire che questo compilatore non esegue
separatamente la costruzione (di default) della locale t
all'inizio della funzione, e quella (per copia) della
non-locale tt alla fine della funzione?  Se e` cosi`,
allora (se il defect-report e` stato accettato) poiche`
interviene codice tale da violare la regola as-if (cioe`
il programma lecitamente puo` distinguere l'ordine o la
eventuale eliminazione/fusione di queste variabili *NON*
di natura temporanea), il compilatore e` in violazione.
VC++ naturalmente non e` in questo caso in violazione
qualsiasi sia la risoluzione (accettato o meno) del
defect report.
Ti consiglio di chiedere su comp.std.c++, dove di certo
sapranno se il defect report era esattamente nei termini
che ricordo e quale sia stato il suo fato; io e` un po'
che non frequento quel gruppo.  Il problema mi pare
d'altronde rilevante piu` che altro per chi scrive
compilatori e suite di test; se anche e` accettato che
questa ottimizzazione Borland e` una violazione (cioe`
che eccede i limiti consentiti da 12.8.15), in codice
di produzione sarebbe comunque prudente evitare di fare
affidamento su punti cosi` "sottili" e controversi dello
standard.  (Naturalmente, NON si puo` fare affidamento
in nessun caso sul fatto che un compilatore standard
debba necessariamente compiere una qualsiasi ottimizzazione
che sia solo CONSENTITA, quindi il codice utente va scritto
in modo da funzionare correttamente sia con, sia senza,
la ottimizzazione in questione).
Alex

il return,
Ciao,
mi rendo conto di aver probabilmente inquinato il codice
da cui e` nato il problema.
Il codice reale al netto di alcune cout e del puntatore
(inseriti per tracciare l'esecuzione) era
#include <iostream>
using namespace std;
class MyClass {
  public:
    MyClass() {
      cout << "C " << endl;
    }
    MyClass(const MyClass& cl)  { cout << "CC" << endl;}
    ~MyClass(){
      cout << "D " << endl;
    }
};
void foo2(MyClass cl_) {
return;
}
MyClass foo1(void) {
  MyClass cl();
  return cl;
}
int main(int argc,char *argv[]) {
  foo2(foo1());
  char c;
  cin >> c;
  return 0;
}
Come dicevo prima, una ottimizzazione in questo
codice che elimini un temporaneo (non l'oggetto cl) me la aspettavo...
sapevo che era prevista. Tuttavia la cosa strana e che
se non si esplicita il copy ctor VC++ non esegue tale ottimizzazione
(il borland la fa in entrambi i casi e riguarda il temporaneo).
E questo il punto che mi sembra molto strano. Mi chiedevo appunto
se cio` fosse normale o meno, ma da quanto riporti mi sembra
appunto una stranezza.
Paolo


 Il Borland C++ 5.02 invece ottimizza entrambi i casi.
Con il Borland C++ 5.5 questo è l'output con il copy ctor esplicito:
C cl
exiting foo1
CC
D cl
Foo2
D
e questo quello togliendo il copy ctor esplicito:
C cl
exiting foo1
D cl
Foo2
D cl
Quindi mi pare si comporti come il tuo 5.02 (a proposito: perché non lo
aggiorni dato che è gratis?). Invece con il DJGPP la prima parte è
uguale ma la seconda presenta in effetti lo stesso comportamento del
Visual C++ 6.0:
C cl
exiting foo1
D cl
Foo2
D cl
D cl
Infatti si può vedere che la copia dell'oggetto avviene anche togliendo
il copy ctor esplicito.
Chi si comporta meglio?
EMG

aggiorni dato che è gratis?).
Infatti possiedo:
BC++ 5.02
BCB 3.0
BC++ 5.5
gcc 2.95.2
VC++ 6.0
:-)


 }
Questo non deve compilare in nessun compilatore standard,
poiche` cl e` una funzione senza argomenti che ritorna
MyClass; non puo` dunque essere trasformata in una MyClass.
A meno che MyClass non abbia un costruttore non-explicit
che accetta un argomento di questo strano tipo:
class MyClass {
public:
    MyClass(MyClass (*p)());
};
ma nel tuo esempio questa peculiarita` mancava.
Sei sicuro che questo sia il codice che compili...?
Alex

Sei sicuro che questo sia il codice che compili...?
No, le parentesi non ci sono.
