Qual è la differenza tra (tipo) valore e tipo (valore)?
-
22-07-2019 - |
Domanda
Qual è la differenza tra
(type)value
e
type(value)
in C ++?
Soluzione
Non c'è differenza; secondo lo standard (§5.2.3):
Un identificatore di tipo semplice (7.1.5) seguito da un elenco di espressioni tra parentesi costruisce un valore del tipo specificato dato l'elenco di espressioni. Se l'elenco di espressioni è una singola espressione, l'espressione di conversione del tipo è equivalente (nella definizione e se definita nel significato) all'espressione di cast corrispondente (5.4).
Poiché la domanda specificava la differenza tra type (value)
e (type) value
, non c'è assolutamente alcuna differenza.
Se e solo se hai a che fare con un elenco separato da virgole di valori può esserci una differenza. In questo caso:
Se l'elenco di espressioni specifica più di un singolo valore, il tipo deve essere una classe con un costruttore adeguatamente dichiarato (8.5, 12.1) e l'espressione T (x1, x2, ...) è in effetti equivalente alla dichiarazione T t (x1, x2, ...); per alcune variabili temporanee inventate t, con il risultato è il valore di t come valore r.
Come sottolineato da Troubadour, ci sono alcuni nomi di tipi per i quali la versione type (value)
semplicemente non verrà compilata. Ad esempio:
char *a = (char *)string;
verrà compilato, ma:
char *a = char *(string);
no. Lo stesso tipo con un nome diverso (ad esempio, creato con un typedef
) può funzionare però:
typedef char *char_ptr;
char *a = char_ptr(string);
Altri suggerimenti
Non c'è differenza; lo standard C ++ (edizioni 1998 e 2003) è chiaro su questo punto. Prova il seguente programma, assicurati di utilizzare un compilatore conforme, ad esempio l'anteprima gratuita all'indirizzo http://comeaucomputing.com/ tryitout / .
#include <cstdlib>
#include <string>
int main() {
int('A'); (int) 'A'; // obvious
(std::string) "abc"; // not so obvious
unsigned(a_var) = 3; // see note below
(long const&) a_var; // const or refs, which T(v) can't do
return EXIT_SUCCESS;
}
Nota: unsigned (a_var)
è diverso, ma mostra un modo in cui quei token esatti possono significare qualcos'altro. Dichiara una variabile denominata a_var
di tipo unsigned e non è affatto un cast. (Se hai familiarità con i puntatori a funzioni o matrici, considera come utilizzare una parentesi attorno a p
in un tipo come void (* pf) ()
o < code> int (* pa) [42] .)
(Gli avvisi sono prodotti poiché queste dichiarazioni non usano il valore e in un vero programma sarebbe quasi sicuramente un errore, ma tutto funziona ancora. Non ho avuto il coraggio di cambiarlo dopo aver fatto tutto in riga up.)
Non c'è alcuna differenza quando entrambi sono cast, ma a volte 'type (value)' non è un cast.
Ecco un esempio della bozza standard N3242, sezione 8.2.1:
struct S
{
S(int);
};
void foo(double a)
{
S w( int(a) ); // function declaration
S y( (int)a ); // object declaration
}
In questo caso 'int (a)' non è un cast perché 'a' non è un valore, è un nome di parametro racchiuso tra parentesi ridondanti. Il documento afferma
L'ambiguità derivante dalla somiglianza tra uno stile di funzione cast e una dichiarazione menzionata in 6.8 possono anche verificarsi nel contesto di una dichiarazione. In quel contesto, la scelta è tra una funzione dichiarazione con un set di parentesi ridondanti attorno a un parametro nome e una dichiarazione di oggetto con un cast in stile funzione come initializer. Proprio come per le ambiguità menzionate in 6.8, il la risoluzione è quella di considerare qualsiasi costrutto che potrebbe essere un dichiarazione una dichiarazione.
In c non esiste un tipo (valore)
, mentre in c / c ++ sia tipo (valore)
che (tipo) valore
sono consentito.
Per illustrare le opzioni in C ++ (solo una ha un controllo di sicurezza)
#include<boost/numeric/conversion/cast.hpp>
using std::cout;
using std::endl;
int main(){
float smallf = 100.1;
cout << (int)smallf << endl; // outputs 100 // c cast
cout << int(smallf) << endl; // outputs 100 // c++ constructor = c cast
cout << static_cast<int>(smallf) << endl; // outputs 100
// cout << static_cast<int&>(smallf) << endl; // not allowed
cout << reinterpret_cast<int&>(smallf) << endl; // outputs 1120416563
cout << boost::numeric_cast<int>(smallf) << endl; // outputs 100
float bigf = 1.23e12;
cout << (int)bigf << endl; // outputs -2147483648
cout << int(bigf) << endl; // outputs -2147483648
cout << static_cast<int>(bigf) << endl; // outputs -2147483648
// cout << static_cast<int&>(bigf) << endl; // not allowed
cout << reinterpret_cast<int&>(bigf) << endl; // outputs 1401893083
cout << boost::numeric_cast<int>(bigf) << endl; // throws bad numeric conversion
}