Namespaces
Variants

Type

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Objetos , referencias , funciones incluyendo especializaciones de plantillas de función , y expresiones tienen una propiedad llamada tipo , que tanto restringe las operaciones permitidas para esas entidades como proporciona significado semántico a las secuencias de bits que de otro modo serían genéricas.

Contenidos

Clasificación de tipos

El sistema de tipos de C++ consta de los siguientes tipos:

(desde C++11)
  • el tipo bool ;
  • tipos de caracteres:
  • tipos de caracteres estrechos:
  • tipos de caracteres ordinarios: char , signed char , unsigned char [1]
  • el tipo char8_t
(desde C++20)
  • tipos de caracteres anchos: char16_t , char32_t , (desde C++11) wchar_t ;
  • tipos enteros con signo:
  • tipos enteros con signo estándar: signed char , short , int , long , long long ;
  • tipos de enteros con signo extendidos (definidos por la implementación);
(since C++11)
  • tipos de enteros sin signo:
  • tipos de enteros sin signo estándar: unsigned char , unsigned short , unsigned , unsigned long , unsigned long long ;
  • tipos de enteros sin signo extendidos (cada uno corresponde a un tipo de entero con signo extendido, y viceversa);
(desde C++11)
(desde C++23)
  • referencia lvalue a tipos de objeto;
  • referencia lvalue a tipos de función;
  • referencia rvalue a tipos de objeto;
  • referencia rvalue a tipos de función;
(desde C++11)
(desde C++11)
  1. signed char y unsigned char son tipos de caracteres estrechos, pero no son tipos de caracteres. En otras palabras, el conjunto de tipos de caracteres estrechos no es un subconjunto del conjunto de tipos de caracteres.

Para cada tipo no calificado-cv que no sea referencia y función, el sistema de tipos admite tres versiones adicionales calificadas-cv de ese tipo ( const , volatile , y const volatile ).

Otras categorías

Un tipo de objeto (ver también std::is_object ) es un tipo (posiblemente calificado con cv) que no es un tipo función, no es un tipo referencia, y no es void (posiblemente calificado con cv).

Los siguientes tipos se denominan colectivamente tipos escalares (ver también std::is_scalar ):

(desde C++11)
  • versiones calificadas cv de estos tipos

Los siguientes tipos se denominan colectivamente tipos de duración implícita :

Los siguientes tipos se denominan colectivamente tipos trivialmente copiables :

Los siguientes tipos se denominan colectivamente tipos de diseño estándar :

(desde C++11)

Diagrama de jerarquía de rasgos de tipo

cpp types v3.svg

Nota: Los elementos de la imagen SVG son clickeables, pero primero debe abrir el diagrama en una nueva pestaña del navegador

Categorías obsoletas

Los siguientes tipos se denominan colectivamente tipos POD (ver también std::is_pod ):

  • tipos escalares
  • clases POD
  • arreglos de dichos tipos
  • versiones calificadas cv de estos tipos
(obsoleto en C++20)

Los siguientes tipos se denominan colectivamente tipos triviales (ver también std::is_trivial ):

(desde C++11)
(obsoleto en C++26)

Tipo definido por el programa

Una especialización definida por el programa es una especialización explícita o una especialización parcial que no forma parte de la biblioteca estándar de C++ y no está definida por la implementación.

Un tipo definido por el programa es uno de los siguientes tipos:

(desde C++11)

Nomenclatura de tipos

Un name puede declararse para referirse a un tipo mediante:

Los tipos que no tienen nombres a menudo necesitan ser referenciados en programas de C++; la sintaxis para eso se conoce como type-id . La sintaxis del type-id que nombra al tipo T es exactamente la sintaxis de una declaración de una variable o función de tipo T , omitiendo el identificador, excepto que el decl-specifier-seq de la gramática de declaración está restringido a type-specifier-seq , y que nuevos tipos pueden definirse solo si el type-id aparece en el lado derecho de una declaración de alias de tipo no plantilla.

int* p;               // declaración de un puntero a int
static_cast<int*>(p); // type-id es "int*"
int a[3];   // declaración de un array de 3 int
new int[3]; // type-id es "int[3]" (llamado new-type-id)
int (*(*x[2])())[3];      // declaración de un array de 2 punteros a funciones
                          // que retornan puntero a array de 3 int
new (int (*(*[2])())[3]); // type-id es "int (*(*[2])())[3]"
void f(int);                    // declaración de una función que toma int y retorna void
std::function<void(int)> x = f; // parámetro de plantilla de tipo es un type-id "void(int)"
std::function<auto(int) -> void> y = f; // mismo
std::vector<int> v;       // declaración de un vector de int
sizeof(std::vector<int>); // type-id es "std::vector<int>"
struct { int x; } b;         // crea un nuevo tipo y declara un objeto b de ese tipo
sizeof(struct { int x; });   // error: no se pueden definir nuevos tipos en una expresión sizeof
using t = struct { int x; }; // crea un nuevo tipo y declara t como un alias de ese tipo
sizeof(static int); // error: especificadores de clase de almacenamiento no son parte de type-specifier-seq
std::function<inline void(int)> f; // error: tampoco los especificadores de función

La parte declarator de la gramática de declaración con el nombre eliminado se denomina abstract-declarator .

Type-id puede ser utilizado en las siguientes situaciones:

(until C++17)

El type-id puede utilizarse con algunas modificaciones en las siguientes situaciones:

  • en la lista de parámetros de una función (cuando se omite el nombre del parámetro), type-id utiliza decl-specifier-seq en lugar de type-specifier-seq (en particular, se permiten algunos especificadores de clase de almacenamiento);
  • en el nombre de una función de conversión definida por el usuario , el declarador abstracto no puede incluir operadores de función o array.

Especificador de tipo elaborado

Los especificadores de tipo elaborados pueden utilizarse para referirse a un nombre de clase previamente declarado (class, struct o union) o a un nombre de enumeración previamente declarado incluso si el nombre estaba oculto por una declaración de no-tipo . También pueden utilizarse para declarar nuevos nombres de clase.

Consulte elaborated type specifier para más detalles.

Tipo estático

El tipo de una expresión que resulta del análisis en tiempo de compilación del programa se conoce como el static type de la expresión. El static type no cambia mientras el programa se está ejecutando.

Tipo dinámico

Si alguna expresión glvalue se refiere a un objeto polimórfico , el tipo de su objeto más derivado se conoce como el tipo dinámico.

// dado
struct B { virtual ~B() {} }; // tipo polimórfico
struct D : B {};               // tipo polimórfico
D d; // objeto más derivado
B* ptr = &d;
// el tipo estático de (*ptr) es B
// el tipo dinámico de (*ptr) es D

Para las expresiones prvalue, el tipo dinámico siempre es el mismo que el tipo estático.

Tipo incompleto

Los siguientes tipos son tipos incompletos :

Todos los demás tipos están completos.

Cualquiera de los siguientes contextos requiere que el tipo T esté completo:

(En general, cuando el tamaño y diseño de T deben conocerse.)

Si cualquiera de estas situaciones ocurre en una unidad de traducción, la definición del tipo debe aparecer en la misma unidad de traducción. De lo contrario, no es requerida.

Un tipo de objeto incompletamente definido puede ser completado:

  • Un tipo de clase (como class X ) puede considerarse incompleto en un punto de una unidad de traducción y considerarse completo más adelante; el tipo class X es el mismo tipo en ambos puntos:
struct X;            // declaración de X, aún no se proporciona la definición
extern X* xp;        // xp es un puntero a un tipo incompleto:
                     // la definición de X no es accesible
void foo()
{
    xp++;            // incorrecto: X está incompleto
}
struct X { int i; }; // definición de X
X x;                 // OK: la definición de X es accesible
void bar()
{
    xp = &x;         // OK: el tipo es "puntero a X"
    xp++;            // OK: X está completo
}
  • El tipo declarado de un objeto array podría ser un array de tipo de clase incompleto y por lo tanto incompleto; si el tipo de clase se completa posteriormente en la unidad de traducción, el tipo array se vuelve completo; el tipo array en esos dos puntos es el mismo tipo.
  • El tipo declarado de un objeto array podría ser un array de límite desconocido y por lo tanto ser incompleto en un punto de una unidad de traducción y completo posteriormente; los tipos array en esos dos puntos ("array de límite desconocido de T " y "array de N T ") son tipos diferentes.

El tipo de un puntero o referencia a un array de límite desconocido apunta permanentemente o se refiere a un tipo incompleto. Un array de límite desconocido nombrado por una typedef declaración se refiere permanentemente a un tipo incompleto. En cualquier caso, el tipo array no puede ser completado:

extern int arr[];   // el tipo de arr es incompleto
typedef int UNKA[]; // UNKA es un tipo incompleto
UNKA* arrp;         // arrp es un puntero a un tipo incompleto
UNKA** arrpp;
void foo()
{
    arrp++;         // error: UNKA es un tipo incompleto
    arrpp++;        // OK: sizeof UNKA* es conocido
}
int arr[10];        // ahora el tipo de arr es completo
void bar()
{
    arrp = &arr;    // OK: conversión de calificación (desde C++20)
    arrp++;         // error: UNKA no puede ser completado
}

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 328 C++98 los miembros de clase de tipo incompleto no estaban prohibidos
si nunca se creaba un objeto del tipo de clase
los miembros de datos no estáticos de clase
deben ser completos
CWG 977 C++98 el momento en que un tipo de enumeración se vuelve
completo en su definición no estaba claro
el tipo es completo una vez que
se determina el tipo subyacente
CWG 1362 C++98 las conversiones definidas por el usuario al tipo T* o T& requerían T completo no requerido
CWG 2006 C++98 los tipos void calificados cv eran tipo objeto y tipo completo excluidos de ambas categorías
CWG 2448 C++98 solo los tipos no calificados cv podían ser tipos integrales y de punto flotante permite tipos calificados cv
CWG 2630 C++98 no estaba claro si una clase se considera completa fuera
de la unidad de traducción donde aparece la definición de la clase
la clase es completa
si su definición es
alcanzable en este caso
CWG 2643 C++98 el tipo de un puntero a array de límite desconocido
no podía completarse (pero ya es completo)
el tipo de array apuntado
no puede completarse
LWG 2139 C++98 el significado de "tipo definido por el usuario" no estaba claro define y usa "tipo definido por
programa" en su lugar
LWG 3119 C++11 no estaba claro si los tipos de clausura son tipos definidos por programa aclarado

Referencias

  • Estándar C++23 (ISO/IEC 14882:2024):
  • 6.8.2 Tipos fundamentales [basic.fundamental]
  • Estándar C++20 (ISO/IEC 14882:2020):
  • 6.8.2 Tipos fundamentales [basic.fundamental]
  • Estándar C++17 (ISO/IEC 14882:2017):
  • 6.9.1 Tipos fundamentales [basic.fundamental]
  • Estándar C++14 (ISO/IEC 14882:2014):
  • 3.9.1 Tipos fundamentales [basic.fundamental]
  • Estándar C++11 (ISO/IEC 14882:2011):
  • 3.9.1 Tipos fundamentales [basic.fundamental]
  • Estándar C++98 (ISO/IEC 14882:1998):
  • 3.9.1 Tipos fundamentales [basic.fundamental]

Véase también

Type traits Interfaces basadas en plantillas en tiempo de compilación para consultar las propiedades de los tipos

Enlaces externos

1. Árbol de tipos de C++0x de Howard Hinnant