C++ Tipos de datos
Al programar con un lenguaje de programación, se necesitan varias variables para almacenar diversa información. La variable conserva la ubicación de memoria del valor que almacena. Esto significa que, cuando se crea una variable, se reserva algo de espacio en la memoria.
Es posible que necesite almacenar información de varios tipos de datos (como tipo carácter, carácter ancho, entero, flotante, doble flotante, booleano, etc.). El sistema operativo asignará memoria y decidirá qué almacenar en la memoria reservada según el tipo de dato de la variable.
Tipos integrados básicos
C++ proporciona a los programadores una amplia variedad de tipos de datos integrados y tipos de datos definidos por el usuario. La siguiente tabla enumera los siete tipos de datos básicos de C++:
| Tipo | Palabra clave |
|---|---|
| Booleano | bool |
| Carácter | char |
| Entero | int |
| Flotante | float |
| Doble flotante | double |
| Sin tipo | void |
| Carácter ancho | wchar_t |
En realidad, wchar_t se obtiene así:
typedef short int wchar_t;
Por lo tanto, el espacio real de wchar_t es el mismo que el de short int.
Algunos tipos básicos se pueden modificar con uno o más modificadores de tipo:
| Modificador | Descripción | Ejemplo |
|---|---|---|
signed | Representa un tipo con signo (por defecto) | signed int x = -10; |
unsigned | Representa un tipo sin signo | unsigned int y = 10; |
short | Representa entero corto | short int z = 100; |
long | Representa entero largo | long int a = 100000; |
const | Representa una constante, el valor no se puede modificar | const int b = 5; |
volatile | Representa que la variable puede modificarse inesperadamente, prohíbe la optimización del compilador | volatile int c = 10; |
mutable | Representa que los miembros de la clase pueden modificarse enconstel objeto | mutable int counter; |
La siguiente tabla muestra la memoria que ocupan varios tipos de variables al almacenar valores, así como los valores máximo y mínimo que una variable de ese tipo puede almacenar.
Nota:Puede haber diferencias entre sistemas; un byte tiene 8 bits.
Nota:De forma predeterminada, int, short y long son con signo, es decir, signed.
Nota:long int ocupa 8 bytes, int ocupa 4 bytes; los primeros compiladores de C definieron long int con 4 bytes e int con 2 bytes. El nuevo estándar de C/C++ es compatible con esta configuración inicial.
| Tipo de datos | Descripción | Tamaño (bytes) | Rango/ejemplo de valores |
|---|---|---|---|
bool | Tipo booleano, representa verdadero o falso | 1 | trueofalse |
char | Tipo carácter, normalmente se usa para almacenar caracteres ASCII | 1 | -128 a 127 o 0 a 255 |
signed char | Tipo carácter con signo | 1 | -128 a 127 |
unsigned char | Tipo carácter sin signo | 1 | 0 a 255 |
wchar_t | Tipo carácter ancho, se usa para almacenar caracteres Unicode | 2 o 4 | Depende de la plataforma |
char16_t | Tipo de carácter Unicode de 16 bits (introducido en C++11) | 2 | 0 a 65,535 |
char32_t | Tipo de carácter Unicode de 32 bits (introducido en C++11) | 4 | 0 a 4,294,967,295 |
short | Entero corto | 2 | -32,768 a 32,767 |
unsigned short | Entero corto sin signo | 2 | 0 a 65,535 |
int | Entero | 4 | -2,147,483,648 a 2,147,483,647 |
unsigned int | Entero sin signo | 4 | 0 a 4,294,967,295 |
long | Entero largo | 4 o 8 | Depende de la plataforma |
unsigned long | Entero largo sin signo | 4 o 8 | Depende de la plataforma |
long long | Entero largo largo (introducido en C++11) | 8 | -9,223,372,036,854,775,808 a 9,223,372,036,854,775,807 |
unsigned long long | Entero largo largo sin signo (introducido en C++11) | 8 | 0 a 18,446,744,073,709,551,615 |
float | Número de coma flotante de precisión simple | 4 | Aprox. ±3.4e±38 (6-7 dígitos significativos) |
double | Número de coma flotante de precisión doble | 8 | Aprox. ±1.7e±308 (15 dígitos significativos) |
long double | Número de coma flotante de precisión extendida | 8, 12 o 16 | Depende de la plataforma |
Tipos nuevos en C++11
| Tipo de datos | Descripción | Ejemplo |
|---|---|---|
auto | Inferencia automática de tipo | auto x = 10; |
decltype | Obtener el tipo de una expresión | decltype(x) y = 20; |
nullptr | Constante de puntero nulo | int* ptr = nullptr; |
std::initializer_list | Tipo de lista de inicialización | std::initializer_list<int> list = {1, 2, 3}; |
std::tuple | Tipo tupla, que puede almacenar varios valores de diferentes tipos | std::tuple<int, float, char> t(1, 2.0, 'a'); |
Tenga en cuenta que el tamaño de almacenamiento de cada tipo está relacionado con la cantidad de bits del sistema, aunque actualmente los sistemas de 64 bits son los más comunes.
A continuación se enumeran las diferencias de tamaño de almacenamiento entre los sistemas de 32 bits y los de 64 bits (igual en Windows):
De la tabla anterior se puede saber que el tamaño de las variables varía según el compilador y la computadora utilizada.
El siguiente ejemplo mostrará el tamaño de varios tipos de datos en su computadora.
Ejemplo
Este ejemplo utilizaendlque insertará un salto de línea después de cada línea,<<El operador << se usa para enviar varios valores a la pantalla,sizeof()El operador sizeof se usa para obtener el tamaño de varios tipos de datos.
Cuando el código anterior se compila y ejecuta, produce los siguientes resultados; los resultados variarán según la computadora utilizada:
type: ************size************** bool: 所占字节数:1 最大值:1 最小值:0 char: 所占字节数:1 最大值: 最小值:? signed char: 所占字节数:1 最大值: 最小值:? unsigned char: 所占字节数:1 最大值:? 最小值: wchar_t: 所占字节数:4 最大值:2147483647 最小值:-2147483648 short: 所占字节数:2 最大值:32767 最小值:-32768 int: 所占字节数:4 最大值:2147483647 最小值:-2147483648 unsigned: 所占字节数:4 最大值:4294967295 最小值:0 long: 所占字节数:8 最大值:9223372036854775807 最小值:-9223372036854775808 unsigned long: 所占字节数:8 最大值:18446744073709551615 最小值:0 double: 所占字节数:8 最大值:1.79769e+308 最小值:2.22507e-308 long double: 所占字节数:16 最大值:1.18973e+4932 最小值:3.3621e-4932 float: 所占字节数:4 最大值:3.40282e+38 最小值:1.17549e-38 size_t: 所占字节数:8 最大值:18446744073709551615 最小值:0 string: 所占字节数:24 type: ************size**************
Tipos de datos derivados
| Tipo de datos | Descripción | Ejemplo |
|---|---|---|
arreglo | Colección de elementos del mismo tipo | int arr[5] = {1, 2, 3, 4, 5}; |
puntero | Tipo que almacena la dirección de memoria de una variable | int* ptr = &x; |
referencia | Alias de una variable | int& ref = x; |
función | Tipo de función, representa la firma de una función | int func(int a, int b); |
estructura | Tipo de datos definido por el usuario, puede contener varios miembros de diferentes tipos | struct Point { int x; int y; }; |
clase | Tipo de datos definido por el usuario, admite encapsulación, herencia y polimorfismo | class MyClass { ... }; |
unión | Varios miembros comparten el mismo bloque de memoria | union Data { int i; float f; }; |
enumeración | Conjunto de constantes enteras definidas por el usuario | enum Color { RED, GREEN, BLUE }; |
Alias de tipo
| Alias | Descripción | Ejemplo |
|---|---|---|
typedef | Definir un alias para un tipo existente | typedef int MyInt; |
using | Definir un alias para un tipo existente (introducido en C++11) | using MyInt = int; |
Tipos de la biblioteca estándar
| Tipo de datos | Descripción | Ejemplo |
|---|---|---|
std::string | Tipo de cadena | std::string s = "Hello"; |
std::vector | Arreglo dinámico | std::vector<int> v = {1, 2, 3}; |
std::array | Arreglo de tamaño fijo (introducido en C++11) | std::array<int, 3> a = {1, 2, 3}; |
std::pair | Contenedor para almacenar dos valores | std::pair<int, float> p(1, 2.0); |
std::map | Contenedor de pares clave-valor | std::map<int, std::string> m; |
std::set | Conjunto de valores únicos | std::set<int> s = {1, 2, 3}; |
Declaración typedef
Puede utilizartypedefpara dar un nuevo nombre a un tipo existente. A continuación se muestra la sintaxis para definir un nuevo tipo con typedef:
typedef type newname;
Por ejemplo, la siguiente declaración le indica al compilador que feet es otro nombre para int:
typedef int feet;
Ahora, la siguiente declaración es completamente legal y crea una variable entera distance:
feet distance;
Tipo enumerado
El tipo enumerado (enumeration) es un tipo de datos derivado en C++, que es un conjunto de varias constantes de enumeración definidas por el usuario.
Si una variable solo tiene algunos valores posibles, se puede definir como tipo enumerado (enumeration). El llamado "enumerar" significa listar los valores de la variable uno a uno; el valor de la variable solo puede estar dentro del rango de los valores listados.
Para crear una enumeración, se necesita la palabra claveenum. La forma general del tipo enumerado es:
enum 枚举名{
标识符[=整型常数],
标识符[=整型常数],
...
标识符[=整型常数]
} 枚举变量;
Si la enumeración no está inicializada, es decir, se omite "= constante entera", entonces comienza desde el primer identificador.
Por ejemplo, el siguiente código define una enumeración de colores, y la variable c es de tipo color. Finalmente, a c se le asigna "blue".
enum color { red, green, blue } c;
c = blue;
De forma predeterminada, el valor del primer nombre es 0, el del segundo nombre es 1, el del tercero es 2, y así sucesivamente. Sin embargo, también puede asignar un valor especial a un nombre, solo necesita agregar un valor inicial. Por ejemplo, en la siguiente enumeración,greentiene el valor 5.
enum color { red, green=5, blue };
Aquí,bluetiene el valor 6, porque de forma predeterminada, cada nombre es 1 mayor que el nombre anterior, pero el valor de red sigue siendo 0.
Conversión de tipos
La conversión de tipos es convertir el valor de un tipo de datos al valor de otro tipo de datos.
En C++ hay cuatro conversiones de tipos: conversión estática, conversión dinámica, conversión de constante y conversión de reinterpretación.
Conversión estática (Static Cast)
La conversión estática es forzar el valor de un tipo de datos al valor de otro tipo de datos.
La conversión estática se usa generalmente para conversiones entre objetos de tipos similares, por ejemplo, convertir el tipo int al tipo float.
La conversión estática no realiza ninguna verificación de tipo en tiempo de ejecución, por lo que puede provocar errores en tiempo de ejecución.
Ejemplo
Conversión dinámica (Dynamic Cast)
La conversión dinámica (dynamic_cast) es un mecanismo en C++ utilizado para realizar downcasting dentro de una jerarquía de herencia.
La conversión dinámica se usa generalmente para convertir un puntero o referencia de clase base a un puntero o referencia de clase derivada.
La conversión dinámica realiza la verificación de tipos en tiempo de ejecución. Si la conversión falla, para tipos de puntero devuelve nullptr, y para tipos de referencia lanza una excepción std::bad_cast.
Sintaxis:
dynamic_cast<目标类型>(表达式)
Tipo de destino: debe ser un tipo de puntero o referencia.
Expresión: el puntero o referencia de clase base que se necesita convertir.
Ejemplo: conversión dinámica de tipos puntero
Salida:
Derived class method
Ejemplo: conversión dinámica de tipos de referencia
#include <typeinfo>
class Base {
public:
virtual ~Base() = default; // La clase base debe tener funciones virtuales
};
class Derived : public Base {
public:
void show() {
std::cout << "Derived class method" << std::endl;
}
};
int main() {
Derived derived_obj;
Base& ref_base = derived_obj; // La referencia de clase base se enlaza a un objeto de clase derivada
try {
// Convertir la referencia de clase base a referencia de clase derivada
Derived& ref_derived = dynamic_cast<Derived&>(ref_base);
ref_derived.show(); // Conversión exitosa, llamar al método de la clase derivada
} catch (const std::bad_cast& e) {
std::cout << "Dynamic cast failed: " << e.what() << std::endl;
}
return 0;
}
Salida:
Derived class method
| Característica | Tipo puntero | Tipo referencia |
|---|---|---|
| Valor de retorno en caso de fallo de conversión | Devuelvenullptr | Lanzastd::bad_castexcepción |
| Escenario de aplicación | Downcasting, verificación de tipos en tiempo de ejecución | Downcasting, verificación de tipos en tiempo de ejecución |
| Sobrecarga de rendimiento | Alta | Alta |
| Requisito de la clase base | Debe tener funciones virtuales | Debe tener funciones virtuales |
Conversión de constante (Const Cast)
La conversión de constante se utiliza para convertir un objeto de tipo const a un objeto de tipo no const.
La conversión de constante solo se puede usar para eliminar el atributo const; no puede cambiar el tipo del objeto.
Ejemplo
Conversión de reinterpretación (Reinterpret Cast)
La conversión de reinterpretación reinterpreta el valor de un tipo de datos como el valor de otro tipo de datos, y se usa generalmente para convertir entre diferentes tipos de datos.
La conversión de reinterpretación no realiza ninguna verificación de tipos, por lo que puede provocar un comportamiento indefinido.
