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

Объекты , ссылки , функции включая специализации шаблонов функций , и выражения обладают свойством под названием тип , которое как ограничивает операции, разрешённые для этих сущностей, так и придаёт семантическое значение иначе универсальным последовательностям битов.

Содержание

Классификация типов

Система типов C++ состоит из следующих типов:

(начиная с C++11)
  • тип bool ;
  • символьные типы:
  • типы узких символов:
  • обычные символьные типы: char , signed char , unsigned char [1]
  • тип char8_t
(начиная с C++20)
  • типы широких символов: char16_t , char32_t , (начиная с C++11) wchar_t ;
  • знаковые целочисленные типы:
  • стандартные знаковые целочисленные типы: signed char , short , int , long , long long ;
  • расширенные знаковые целочисленные типы (определяемые реализацией);
(since C++11)
  • беззнаковые целочисленные типы:
  • стандартные беззнаковые целочисленные типы: unsigned char , unsigned short , unsigned , unsigned long , unsigned long long ;
  • расширенные беззнаковые целочисленные типы (каждый соответствует расширенному знаковому целочисленному типу, и наоборот);
(since C++11)
(since C++23)
  • lvalue-ссылки на объектные типы;
  • lvalue-ссылки на функциональные типы;
  • rvalue-ссылки на объектные типы;
  • rvalue-ссылки на функциональные типы;
(начиная с C++11)
(since C++11)
  1. signed char и unsigned char являются типами узких символов, но они не являются символьными типами. Другими словами, множество типов узких символов не является подмножеством множества символьных типов.

Для каждого неквалифицированного по cv типа, кроме ссылки и функции, система типов поддерживает три дополнительные cv-квалифицированные версии этого типа ( const , volatile и const volatile ).

Другие категории

Тип объекта (см. также std::is_object ) — это (возможно, cv-квалифицированный) тип, который не является типом функции, не является ссылочным типом и не является (возможно, cv-квалифицированным) void .

Следующие типы в совокупности называются скалярными типами (см. также std::is_scalar ):

(начиная с C++11)
  • cv-квалифицированные версии этих типов

Следующие типы в совокупности называются типами с неявным временем жизни :

Следующие типы в совокупности называются тривиально копируемыми типами :

Следующие типы в совокупности называются типами со стандартной компоновкой :

(since C++11)

Иерархическая диаграмма метатипов

cpp types v3.svg

Примечание: элементы SVG-изображения являются кликабельными, но сначала необходимо открыть диаграмму в новой вкладке браузера

Устаревшие категории

Следующие типы в совокупности называются POD типами (см. также std::is_pod ):

  • скалярные типы
  • POD классы
  • массивы таких типов
  • cv-квалифицированные версии этих типов
(устарело в C++20)

Следующие типы в совокупности называются тривиальными типами (см. также std::is_trivial ):

(начиная с C++11)
(устареет в C++26)

Пользовательский тип данных

Программно-определенная специализация — это явная специализация или частичная специализация , которая не является частью стандартной библиотеки C++ и не определена реализацией.

A program-defined type — это один из следующих типов:

  • A non- closure (since C++11) class type или enumeration type который не является частью стандартной библиотеки C++ и не определён реализацией.
(начиная с C++11)
  • Создание экземпляра специализации, определённой в программе.

Наименование типов

Имя name может быть объявлено для ссылки на тип с помощью:

Типы, которые не имеют имён, часто требуют упоминания в программах на C++; синтаксис для этого известен как type-id . Синтаксис type-id, который именует тип T , в точности соответствует синтаксису объявления переменной или функции типа T , с опущенным идентификатором, за исключением того, что decl-specifier-seq в грамматике объявления ограничивается type-specifier-seq , и что новые типы могут быть определены только если type-id появляется в правой части объявления псевдонима нетемплейтного типа.

int* p;               // объявление указателя на int
static_cast<int*>(p); // type-id это "int*"
int a[3];   // объявление массива из 3 int
new int[3]; // type-id это "int[3]" (называется new-type-id)
int (*(*x[2])())[3];      // объявление массива из 2 указателей на функции
                          // возвращающие указатель на массив из 3 int
new (int (*(*[2])())[3]); // type-id это "int (*(*[2])())[3]"
void f(int);                    // объявление функции принимающей int и возвращающей void
std::function<void(int)> x = f; // параметр шаблона типа это type-id "void(int)"
std::function<auto(int) -> void> y = f; // то же самое
std::vector<int> v;       // объявление вектора int
sizeof(std::vector<int>); // type-id это "std::vector<int>"
struct { int x; } b;         // создает новый тип и объявляет объект b этого типа
sizeof(struct { int x; });   // ошибка: нельзя определять новые типы в выражении sizeof
using t = struct { int x; }; // создает новый тип и объявляет t как псевдоним этого типа
sizeof(static int); // ошибка: спецификаторы класса хранения не являются частью type-specifier-seq
std::function<inline void(int)> f; // ошибка: спецификаторы функций также не входят

Часть декларатора в грамматике объявлений с удалённым именем называется абстрактным-декларатором .

Type-id может использоваться в следующих ситуациях:

(до C++17)

Type-id может использоваться с некоторыми модификациями в следующих ситуациях:

  • в списке параметров функции (когда имя параметра опущено), type-id использует decl-specifier-seq вместо type-specifier-seq (в частности, разрешены некоторые спецификаторы класса хранения);
  • в имени пользовательской функции преобразования , абстрактный декларатор не может включать операторы функции или массива.

Уточняющий спецификатор типа

Уточненные спецификаторы типа могут использоваться для ссылки на ранее объявленное имя класса (class, struct или union) или на ранее объявленное имя перечисления, даже если имя было скрыто не-типовым объявлением . Они также могут использоваться для объявления новых имен классов.

См. elaborated type specifier для получения подробной информации.

Статический тип

Тип выражения, который определяется в результате анализа программы на этапе компиляции, называется статическим типом выражения. Статический тип не изменяется во время выполнения программы.

Динамический тип

Если некоторое glvalue выражение ссылается на полиморфный объект , тип его наиболее производного объекта называется динамическим типом.

// дано
struct B { virtual ~B() {} }; // полиморфный тип
struct D : B {};               // полиморфный тип
D d; // самый производный объект
B* ptr = &d;
// статический тип (*ptr) - B
// динамический тип (*ptr) - D

Для выражений prvalue динамический тип всегда совпадает со статическим типом.

Неполный тип

Следующие типы являются неполными типами :

  • тип void (возможно cv -квалифицированный);
  • неполноопределенные объектные типы :
    • классовый тип, который был объявлен (например, с помощью forward declaration ), но не определен;
    • array of unknown bound ;
    • массив элементов неполного типа;
    • enumeration type от точки объявления до момента определения его базового типа.

Все остальные типы являются полными.

Любой из следующих контекстов требует, чтобы тип T был полным:

(В общем случае, когда размер и расположение T должны быть известны.)

Если любая из этих ситуаций возникает в единице трансляции, определение типа должно присутствовать в той же единице трансляции. В противном случае это не требуется.

Неполностью определённый тип объекта может быть завершён:

  • Тип класса (такой как class X ) может считаться неполным в одной точке единицы трансляции и считаться полным позже; тип class X является одним и тем же типом в обеих точках:
struct X;            // объявление X, определение пока не предоставлено
extern X* xp;        // xp - указатель на неполный тип:
                     // определение X недоступно
void foo()
{
    xp++;            // некорректно: X неполный
}
struct X { int i; }; // определение X
X x;                 // OK: определение X доступно
void bar()
{
    xp = &x;         // OK: тип "указатель на X"
    xp++;            // OK: X полный
}
  • Объявленный тип массива может быть массивом незавершенного типа класса и, следовательно, незавершенным; если тип класса завершается позже в единице трансляции, тип массива становится завершенным; тип массива в этих двух точках является одним и тем же типом.
  • Объявленный тип массива может быть массивом неизвестной границы и, следовательно, быть незавершенным в одной точке единицы трансляции и завершенным позже; типы массивов в этих двух точках ("массив неизвестной границы T " и "массив N T ") являются разными типами.

Тип указателя или ссылки на массив неизвестной границы постоянно указывает на или ссылается на неполный тип. Массив неизвестной границы, именованный с помощью typedef объявления, постоянно ссылается на неполный тип. В любом случае тип массива не может быть завершён:

extern int arr[];   // тип arr является неполным
typedef int UNKA[]; // UNKA является неполным типом
UNKA* arrp;         // arrp - указатель на неполный тип
UNKA** arrpp;
void foo()
{
    arrp++;         // ошибка: UNKA является неполным типом
    arrpp++;        // OK: размер UNKA* известен
}
int arr[10];        // теперь тип arr является полным
void bar()
{
    arrp = &arr;    // OK: преобразование квалификации (начиная с C++20)
    arrp++;         // ошибка: UNKA не может быть завершен
}

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.

DR Применяется к Поведение в опубликованной версии Корректное поведение
CWG 328 C++98 члены класса неполного типа не запрещались
если объект типа класса никогда не создавался
нестатические члены данных класса
должны быть полными
CWG 977 C++98 момент, когда тип перечисления становится
полным в его определении, был неясен
тип становится полным после
определения базового типа
CWG 1362 C++98 пользовательские преобразования в тип T* или T& требовали T быть полным не требуется
CWG 2006 C++98 cv-квалифицированные void типы были типами объектов и полными типами исключены из обеих категорий
CWG 2448 C++98 только cv-неквалифицированные типы могли быть целочисленными и типами с плавающей точкой разрешает cv-квалифицированные типы
CWG 2630 C++98 было неясно, считается ли класс полным вне
единицы трансляции, где появляется определение класса
класс считается полным
если его определение
достижимо в этом случае
CWG 2643 C++98 тип указателя на массив неизвестной границы
не мог быть завершен (но он уже полный)
тип массива, на который указывают,
не может быть завершен
LWG 2139 C++98 значение термина "пользовательский тип" было неясным определяет и использует "программно-
определенный тип" вместо этого
LWG 3119 C++11 было неясно, являются ли типы замыканий программно-определенными типами прояснено

Ссылки

  • Стандарт C++23 (ISO/IEC 14882:2024):
  • 6.8.2 Фундаментальные типы [basic.fundamental]
  • Стандарт C++20 (ISO/IEC 14882:2020):
  • 6.8.2 Фундаментальные типы [basic.fundamental]
  • Стандарт C++17 (ISO/IEC 14882:2017):
  • 6.9.1 Фундаментальные типы [basic.fundamental]
  • Стандарт C++14 (ISO/IEC 14882:2014):
  • 3.9.1 Фундаментальные типы [basic.fundamental]
  • Стандарт C++11 (ISO/IEC 14882:2011):
  • 3.9.1 Фундаментальные типы [basic.fundamental]
  • Стандарт C++98 (ISO/IEC 14882:1998):
  • 3.9.1 Фундаментальные типы [basic.fundamental]

Смотрите также

Type traits Интерфейсы на основе шаблонов времени компиляции для запроса свойств типов
C documentation для Type

Внешние ссылки

1. Дерево типов C++0x от Howard Hinnant