Newsgroup: it.comp.lang.c++
Titolo: funzioni inline

Salve a tutti,
volevo chiedere un paio di cosette sulle funzioni inline:
1. Dichiarare e definire una funzione all'interno dell definizione di 
classe la rende inline; questo però non mi piace in quanto se un utente 
delle mie classi apre l'header nel quale la classe è definita vede il 
codice delle funzioni inline; se nella classe dichiaro solo la funzione 
e quando vado a definirla (nell'unità di compilazione) antepongo alla 
sua firma la keyword inline (come si farebbe in C) ottengo lo stesso che 
la funzione membro è inline giusto?
2. Una funzione inline può essere virtual? Teoricamente no, perchè una 
funzione inline non è allocata in memoria ma sostituita col suo codice a 
tempo di compilazione quindi non può essere ricavato il puntatore a 
funzione da mettere nella VTABLE. Se però dichiaro virtual una funzione 
inline il compilatore (g++) non si lamenta; come mai? Rende la funzione 
non inline?
Saluti e grazie, Alberto

 inline il compilatore (g++) non si lamenta; come mai?
Il compilatore predilige il "virtual" all'"inline", quindi è libero di
ignorare il fatto che tu abbia specificato che la funzione deve essere
espansa in linea.  Che io sappia però, un compilatore è libero di
adottare la tecnica mista, ovvero ricorrere alla vtable quando serve ed
espandere in linea, allo stesso tempo, quando è sicuro farlo.

 volevo chiedere un paio di cosette sulle funzioni inline:
In generale, non hai nessuna garanzia che funzioni dichiarate "inline" 
vengano effettivamente espanse in linea.
Il compilatore, normalmente, non può usare l'espansione in linea per 
funzioni virtuali /chiamate virtualmente/.
Kiuhnm

 non inline?
Ti hano gia' risposto altri.
Ciao,
Nicola

 funzione.
Scusa, forse non ho espresso bene la mia domanda: so che il compilatore 
non è obbligato a rendere inline una funzione dichiarata come tale per 
le sue buone ragioni, quello che chiedevo io era se ci fosse differenza 
fra il definire la funzione all'interno della classe (e quindi chiedere 
implicitamente al compilatore di renderla inline) ed il dare solo la 
dichiarazione all'interno della classe dandone la definizione in 
un'unità separata ed anteponendovi alla firma la keyword inline.
In soldoni, se il compilatore decide di rendere inline una funzione 
dichiarata come tale all'interno della classe, allora sono sicuro che 
usando il secondo metodo renderà lo stesso la funzione inline?
Grazie a tutti per le risposte, Alberto

 (g++) non si lamenta; come mai? Rende la funzione non inline?
Probabilemente, se chiama la funzione attraverso un puntatore,
e il compilatore non può vedere il vero tipo. Farà in ogni caso
une imagine della funzione non inline, dal modo di metterne
l'indirizzo nella vtable. Ma se sà il tipo reale al sito del
chiamato, può communque metterla inline. Da essempio:
    Derived d ;
    d.f() ;         // Può essere inline, anche se f è virtual
    Base*   p = new Derived ;
    p->f();         // Ed anche qui, perche il compilatore può
                    // vedere che p punta un Derived.
    if ( c ) {
        p = new D1 ;
    } else {
        p = new D2 ;
    }
    p->f() ;        // Qui invece, non può essere inline, almeno
                    // che il compilatore genera qualcosa comme:
                    //  if( typeof( *p ) == D1 ) {
                    //      p->f() ;   // D1::f() inline
                    //  } else {
                    //      p->f() ;   // Chiama a traverso il vtable
                    //  }
--
James Kanze (GABI Software)             
email:james...@gmail.com
Conseils en informatique orientée objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, 
+33 (0)1 30 23 00 34

 usando il secondo metodo renderà lo stesso la funzione inline?
Allora i due programmi seguenti sono equivalenti:
// primo
struct s {
  int f() { return 42; }
};
int main() {
  return f();
}
//secondo
struct s {
  int f();
};
inline int s::f() {
  return 42;
}
int main() {
  return f();
}
I problemi sorgono quando decidi come suddividere il tuo codice in
header e unita' di traduzione. Il problema e' che per poter espandere
inline il tuo codice il compilatore deve conoscere la definizione della
funzione; ricorda che i compilatori C++ compilano ciascuna unita' di
traduzione separatamente.
Se tu suddividi il tuo codice ad esempio cosi':
// file s.h
struct s {
  int f();
};
// file main.cpp
int main() {
  return f();
}
Il compilatore non solo non sa come espandere inline f(), ma non sa
nemmeno che deve farlo e quindi genera una normale chiamata out of line
non risolta (cioe' non sa ancora dove e' f()). Se poi hai da un altra
parte
// file s.cpp
inline int s::f() {
  return 42;
}
Qui il compilatore saprebbe espandere f() inline, ma non ha nessuna
chiamata dove farlo. In piu' non ha modo di sapere che deve espandere
f() out of line per risolvere la chiamata presente in main(). Il
risultato e' un errore di linking.
La conclusione e' che puoi scrivere la tua funzione inline al di fuori
della definizione della classe, ma questa deve comunque stare nello
header corrispondente (o in un altro header, che pero' devi poi
ricordarti di includere dove serve).
Talvolta lo faccio perche' risulta piu' pratico commentare il codice,
soprattutto se si vogliono utilizzare generatori di documentazione.
Ciao,
Nicola

 traduzione separatamente.
Di norma si, alcuni pero' posticipano la generazione del codice per 
ottimizzarlo in fase di linking (Intel C++ da almeno un paio di versioni, 
VC++ dalla 2005).
In questo caso possono rendere inline funzioni definite su unita' di 
compilazione separate da quelle di utilizzo. Ma e', ovviamente, 
un'ottimizzazione, non una specifica del linguaggio.
--*PaN!* 

 volevo chiedere un paio di cosette sulle funzioni inline:
mi pare che dovunque tu la usi, implicita o esplicita, la 
"direttiva" inline sia simile a "register" nelle variabili 
automatiche (puoi dichiararne decine register, ma se sei 
fortunato ti accetta le prime due, e se sei molto fortunato, 
tali due non sono le prime dichiarate nello scope ma le due più 
intensamente usate. Tutte le altre richieste sono scartate per 
insufficienza di registri standard effettivi e liberi).
Sono solo richieste, suggerimenti al compilatore ad ottimizzare 
in un certo modo, ma esso le può ignorare senza nemmeno warning.
Sulle inline tieni conto anche di una cosa. Se il codice è 
effetticamente molto compatto, il vantaggio è certo. Se il 
codice è ingombrante, la velocità è controbilanciata da un 
codice compilato molto più ingombrante (come per le macro). In 
casi limite e di memoria scarsa disponibile, un programma 
teoricamente veloce ma molto pesante e grosso, può girare più 
lento di uno intrinsecamente più lento ma compatto (per 
questioni tipo swap etc). Certo .... ho citato un caso limite.
ciao
Soviet


 questioni tipo swap etc). Certo .... ho citato un caso limite.
Sulle CPU moderne il caso puo' non essere affatto limite, dal momento
che ogni "cache miss", ovvero il non trovare un dato nella cache
dovendolo reperire quindi in una cache di secondo livello, o in RAM, o
su disco, puo' penalizzare le prestazioni pesantemente.
Ciao,
Nicola