¿Cuál es la diferencia entre el valor (tipo) y el tipo (valor)?
-
22-07-2019 - |
Pregunta
¿Cuál es la diferencia entre
(type)value
y
type(value)
en C ++?
Solución
No hay diferencia; según el estándar (§5.2.3):
Un especificador de tipo simple (7.1.5) seguido de una lista de expresiones entre paréntesis construye un valor del tipo especificado dada la lista de expresiones. Si la lista de expresiones es una sola expresión, la expresión de conversión de tipo es equivalente (en definición y si está definida en significado) a la expresión de conversión correspondiente (5.4).
Como la pregunta especifica la diferencia entre tipo (valor)
y (tipo) valor
, no hay absolutamente ninguna diferencia.
Si y solo si se trata de una lista de valores separados por comas, puede haber una diferencia. En este caso:
Si la lista de expresiones especifica más de un solo valor, el tipo será una clase con un constructor adecuadamente declarado (8.5, 12.1), y la expresión T (x1, x2, ...) es equivalente en efecto a la declaración T t (x1, x2, ...); para algunas variables temporales inventadas t, cuyo resultado es el valor de t como valor de r.
Como señaló Troubadour, hay ciertos nombres de tipos para los que la versión type (value)
simplemente no se compilará. Por ejemplo:
char *a = (char *)string;
se compilará, pero:
char *a = char *(string);
no lo hará. Sin embargo, el mismo tipo con un nombre diferente (por ejemplo, creado con un typedef
) puede funcionar:
typedef char *char_ptr;
char *a = char_ptr(string);
Otros consejos
No hay diferencia; El estándar C ++ (ediciones 1998 y 2003) es claro sobre este punto. Pruebe el siguiente programa, asegúrese de utilizar un compilador que sea compatible, como la vista previa gratuita en 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)
es diferente, pero muestra una forma en que esos tokens exactos pueden significar otra cosa. Está declarando una variable llamada a_var
de tipo unsigned, y no es una conversión en absoluto. (Si está familiarizado con los punteros a funciones o matrices, considere cómo debe usar un parens alrededor de p
en un tipo como void (* pf) ()
o < code> int (* pa) [42] .)
(Las advertencias se producen ya que estas declaraciones no usan el valor y en un programa real que seguramente sería un error, pero todo sigue funcionando. Simplemente no tuve el corazón para cambiarlo después de hacer que todo alineara arriba)
No hay diferencia cuando ambos son lanzamientos, pero a veces 'type (value)' no es un lanzamiento.
Aquí hay un ejemplo del borrador estándar N3242, sección 8.2.1:
struct S
{
S(int);
};
void foo(double a)
{
S w( int(a) ); // function declaration
S y( (int)a ); // object declaration
}
En este caso, 'int (a)' no es una conversión porque 'a' no es un valor, es un nombre de parámetro rodeado de paréntesis redundantes. El documento dice
La ambigüedad que surge de la similitud entre un estilo de función emitir y una declaración mencionada en 6.8 también puede ocurrir en el contexto de una declaración. En ese contexto, la elección es entre una función declaración con un conjunto redundante de paréntesis alrededor de un parámetro nombre y una declaración de objeto con un molde de estilo de función como el inicializador Al igual que para las ambigüedades mencionadas en 6.8, el la resolución es considerar cualquier construcción que posiblemente pueda ser una declaración una declaración.
En c no hay type (value)
, mientras que en c / c ++ tanto type (value)
como (type) value
son permitido.
Para ilustrar sus opciones en C ++ (solo una tiene una verificación de seguridad)
#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
}