Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Типи сердечників

Godot має багатий набір класів і шаблонів, які складають його ядро, і все побудовано на них.

У цьому довіднику спробуємо перерахувати їх для кращого розуміння.

Виділення пам'яті

У Godot є багато хитрощів для забезпечення безпеки пам'яті та відстеження її використання. Через це не слід використовувати звичайні виклики бібліотек C та C++. Натомість передбачено кілька замін.

Для розподілу в стилі C Godot надає кілька макросів:

memalloc(size)
memrealloc(pointer)
memfree(pointer)

Вони еквівалентні звичайним функціям malloc(), realloc() та free() зі стандартної бібліотеки C.

Для розподілу в стилі C++ передбачені спеціальні макроси:

memnew(Class)
memnew(Class(args))
memdelete(instance)

memnew_arr(Class, amount)
memdelete_arr(pointer_to_array)

Вони еквівалентні відповідно new, delete, new[] та delete[].

memnew/memdelete також використовують трохи магії C++ для автоматичного виклику функцій post-init та pre-release. Наприклад, це використовується для сповіщення об'єктів одразу після їх створення та безпосередньо перед їх видаленням.

Контейнери

Godot надає власний набір контейнерів, що означає, що контейнери STL, такі як std::string та std::vector, зазвичай не використовуються в кодовій базі. Див. Чому Godot не використовує STL (Standard Template Library)? для отримання додаткової інформації.

Значок 📜 позначає, що тип є частиною Variant. Це означає, що його можна використовувати як параметр або повернене значення методу, що надається API сценаріїв.

Тип даних Godot

Найближчий тип даних C++ STL

Коментар

String 📜

std::string

Використовуйте це як тип рядка «за замовчуванням». String використовує кодування UTF-32 для спрощення обробки завдяки фіксованому розміру символів.

Vector

std::vector

Використовуйте це як «типовий» тип вектора. Використовує семантику копіювання при записі (COW). Це означає, що він, як правило, повільніший, але його можна копіювати майже безкоштовно. Використовуйте LocalVector, якщо COW не потрібний і важлива продуктивність.

HashSet

std::unordered_set

Використовуйте це як тип набору "за замовчуванням".

AHashMap

std::unordered_map

Використовуйте це як тип карти "за замовчуванням". Не зберігає порядок вставки. Зверніть увагу, що вказівники на карту, а також ітератори, нестабільні при мутаціях. Якщо потрібна будь-яка з цих можливостей, використовуйте замість цього HashMap.

StringName 📜

std::string

Використовує інтернування рядків для швидкого порівняння. Використовуйте це для статичних рядків, на які часто посилаються та які використовуються в кількох місцях у рушії.

LocalVector

std::vector

Ближчий до std::vector за семантикою, не використовує копіювання під час запису (COW), тому швидший за Vector. Віддавайте перевагу йому над Vector, коли не потрібне дешеве копіювання.

Array 📜

std::vector

Значення можуть бути будь-якого типу Variant. Статична типізація не нав'язана. Використовується спільний підрахунок посилань, подібно до std::shared_ptr. Використовує Vector<Variant> внутрішньо.

TypedArray 📜

std::vector

Підклас Array, але зі статичним типізуванням для його елементів. Не плутати з Packed*Array, який внутрішньо є Vector.

Packed*Array 📜

std::vector

Псевдонім Vector, наприклад, PackedColorArray = Vector<Color>. Доступний лише обмежений список типів упакованих масивів (інакше використовуйте TypedArray).

List

std::list

Тип зв'язаного списку. Зазвичай повільніший за інші типи масивів/векторів. Віддавайте перевагу використанню інших типів у новому коді, окрім випадків, коли використання List дозволяє уникнути необхідності перетворення типів.

FixedVector

std::array

Вектор з фіксованою ємністю (більш схожий на boost::container::static_vector). Цей тип контейнера є ефективнішим за інші вектороподібні типи, оскільки він не виконує виділення пам'яті купи.

Span

std::span

Представляє доступ лише для читання до суміжного масиву без необхідності копіювання будь-яких даних. Зверніть увагу, що Span розроблено як високопродуктивний API: він не виконує перевірки правильності параметрів так само, як ви, можливо, звикли до інших контейнерів Godot. Використовуйте обережно. Span можна створити з більшості масивоподібних контейнерів (наприклад, vector.span()).

RBSet

std::set

Використовує червоно-чорне дерево для швидшого доступу.

VSet

std::flat_set

Використовує семантику копіювання під час запису (COW). Це означає, що він загалом повільніший, але його можна копіювати майже безкоштовно. Переваги VSet у продуктивності не встановлені, тому перевагу надають іншим типам.

HashMap

std::unordered_map

Захисний (надійний, але повільний) тип карти. Зберігає порядок вставки. Вказівники на ключі та значення, а також ітератори, стабільні при змінах. Використовуйте цей тип карти, коли потрібна будь-яка з цих можливостей. В іншому випадку використовуйте AHashMap.

RBMap

std::map

Map type that uses a red-black tree to find keys. The performance benefits of RBMap aren't established, so prefer using other types.

Dictionary 📜

std::unordered_map

Ключі та значення можуть бути будь-якого типу Variant. Статична типізація не нав'язана. Використовує спільний підрахунок посилань, подібно до std::shared_ptr. Зберігає порядок вставки. Внутрішньо використовує HashMap<Variant>.

TypedDictionary 📜

std::unordered_map

Підклас Dictionary, але зі статичною типізацією для ключів та значень.

Pair

std::pair

Зберігає одну пару. Див. також KeyValue у тому ж файлі, який використовує ключі лише для читання.

Безпека переїзду

Контейнери Годо припускають, що їхні елементи є «тривіально переміщуваними».

Це означає, що якщо ви зберігаєте в ньому типи даних, які мають вказівники на себе або іншим чином не є тривіально переміщуваними, Godot може аварійно завершити роботу. Зауважте, що зберігання вказівників на об'єкти, які не є тривіально переміщуваними, таких як деякі підкласи Object, не є проблематичним та підтримується.

Причина припускати тривіальну переміщуваність полягає в тому, що це дозволяє нам використовувати важливі методи оптимізації, такі як переміщення за допомогою memcpy або realloc.

GH-100509 відстежує це рішення.

Багатопотоковість / Паралелізм

Дивись також

Більше інформації про стратегії багатопотоковості можна знайти за посиланням Використання кількох потоків.

Жоден із контейнерів Godot не є потокобезпечним. Коли ви очікуєте, що до них звертатимуться кілька потоків, ви повинні використовувати багатопотоковий захист.

Зверніть увагу, що деякі з перелічених тут типів також доступні через прив'язки, але ці типи прив'язок обгорнуті class_RefCounted (знаходиться в просторі імен CoreBind::). З міркувань ефективності, коли це можливо, надавайте перевагу переліченим тут примітивам.

Тип даних Godot

Найближчий тип даних C++ STL

Коментар

Mutex

std::recursive_mutex

Рекурсивний тип м'ютексу. Використовуйте MutexLock lock(mutex) для його блокування.

BinaryMutex

std::mutex

Нерекурсивний тип м'ютексу. Використовуйте MutexLock lock(mutex) для його блокування.

RWLock

std::shared_mutex

Тип м'ютексу з підтримкою читання та запису. Використовуйте RWLockRead lock(mutex) або RWLockWrite lock(mutex) для його блокування.

SafeBinaryMutex

std::mutex

Рекурсивний тип м'ютексу, який можна використовувати з ConditionVariable. Використовуйте MutexLock lock(mutex) для його блокування.

ConditionVariable

std::condition_variable

Тип умовної змінної, що використовується з SafeBinaryMutex.

Semaphore

std::counting_semaphore

Тип семафора підрахунку.

SafeNumeric

std::atomic

Шаблонний атомарний тип, призначений для чисел.

SafeFlag

std::atomic_bool

Атомарний тип Bool.

SafeRefCount

std::atomic

Атомарний тип, призначений для підрахунку посилань. Відмовиться збільшувати лічильник посилань, якщо він дорівнює 0.

Типи математики

У каталозі core/math доступно кілька типів лінійної математики:

Шлях до вузла

Це спеціальний тип даних, який використовується для зберігання шляхів у дереві сцени та оптимізованого посилання на них:

RID

RID – це ідентифікатори ресурсів. Сервери використовують їх для посилання на дані, що зберігаються в них. RID непрозорі, тобто до даних, на які вони посилаються, не можна отримати безпосередній доступ. RID унікальні, навіть для різних типів даних, на які посилаються: