Использует std :: необязательный & lt; int & gt; так же эффективно, как использование int?

У меня есть структура данных quad- / octree. Я храню дочерние индексы / ptrs ячейки в массиве. Каждая позиция в массиве представляет местоположение дочернего элемента относительно его родителя, например, в 2D:

// _____________
// |     |     |
// |  2  |  3  |
// |_____|_____|
// |     |     |
// |  0  |  1  |
// |_____|_____|
// for each cell, 4 children are always stored in row-major order
std::vector<std::array<Integer,4>> children;

Я знаю, что максимальное количество детей является подмножеством значений, которые Integer Тип может представлять. Таким образом, я могу определить, отсутствует ли в ячейке дочерний элемент, используя «магическое» значение, например -1 за Integer = int, или же std::numeric_limits<unsigned>::max() за Integer = unsigned, Это то, что std::optional<Integer> не могу предположить.

Насколько я понял, это использование магических ценностей является одним из смысла std::optional, Тем не менее, я беспокоюсь о производительности std::vector<std::optional<int>> во внутренних петлях.

Так,

  • Будет ли производительность std::vector<std::optional<int>> быть хуже, чем у std::vector<int>? (Я уже делаю сравнение для «несуществующего» значения).

  • Или, может ли реализация std::optional оптимизировать, чтобы предложить ту же производительность, что и сырье int? И как?

смешивание std::optional в возвращаемом типе моих функций и магических значений в моей структуре данных звучит как очень плохая идея. Я предпочитаю быть последовательным и либо использовать один или другой (по крайней мере, в том же контексте). Хотя я мог бы перегрузить функцию, которая выполняет сравнение с магическим числом:

template<T> bool is_valid(const T& t) {
return /* comparison with magic value for t */;
}

для необязательных типов.

13

Решение

std::optional потребует дополнительного хранилища и поместит меньшее количество значений в кеш (кажется, вы уже знаете причину этого).

Я не думаю, что неправильно хранить внутреннее значение в вашей структуре данных от значения, предоставляемого общедоступным API, если внутреннее представление полностью скрыто от пользователей.

Кроме того, я предлагаю вам выделить магическое число в одну пару inline функции преобразования.

Компилятор должен помочь вам не забывать постоянно использовать функции преобразования, генерируя ошибки типа, если вы забудете. Вы могли бы даже использовать тонкую структуру-обертку для int в вашей внутренней структуре данных, чтобы гарантировать, что неявного преобразования не существует (или определить пользовательское преобразование).

class CompressedOptionalUInt
{
static const unsigned SENTINEL_MISSING = std::numeric_limits<unsigned>::max();
unsigned value;

public:
CompressedOptionalUInt(std::optional<unsigned> val) : value(!val? SENTINEL_MISSING: *val) {}
operator std::optional<unsigned>() const { ... }
};

а затем использовать std::array<CompressedOptionalUInt>,

Сделать это в шаблоне, для каждого типа которого нужно определить только дозорного, должно быть довольно просто.

14

Другие решения

Нет, это не так эффективно. Как вы можете видеть из эталонная реализация он должен хранить, обновлять и проверять дополнительные значения.

3

По вопросам рекламы [email protected]