Учитывая, что каждый экземпляр std::unordered_set<uint_32>
по-прежнему будет приводить как минимум к еще одному выделению памяти в куче (внутренне), реально достижимая экономия жестко ограничена. Вы собираетесь сэкономить менее 50% необходимого распределения кучи.
Важно то, что после создания узла он не будет удален, пока не будет удалено все дерево.
Перераспределение все еще происходит в std::vector
по мере его роста. В отличие от неподвижных выделений в куче, это дополнительно включает перемещение уже выделенных узлов. В зависимости от того, какие другие атрибуты имеют ваши элементы node
, это может быть еще дороже. Вам также необходимо убедиться, что ваш класс node
совместим с семантикой перемещения.
Поскольку std::unordered_set
также выделяется в куче, вы также не сможете избежать возникающей фрагментации памяти.
В общем, если вы не ожидаете, что будете ограничены производительностью распределения кучи или у вас нет варианта использования для обхода дерева, независимого от порядка, сжатие node
экземпляров, вероятно, не будет стоить усилий.
Потенциально разумной оптимизацией будет замена std::unordered_set<node*>
на std::unordered_set<node>
. Если вам не нужно это косвенное обращение в этом месте (внешние указатели?), Это сэкономит вам столько же, сколько и ваша собственная попытка, без ущерба для возможностей отладки.
Реализация необходимой функции ha sh и оператора равенства для node
обычно легко.
Если производительность вызывает реальную озабоченность, и у вас также есть (разумная) верхняя граница количества дочерних узлов на узел, вы можете подумать о замене std::unordered_set<uint_32> children
на std::array<uint_32, n> children
вместо использования std::find()
для обнаружения коллизий.
Причина этого довольно проста: node
становится TriviallyCopyable , что внутренне сокращает перераспределение до простого memcpy
. Примерно для 16 детей это будет нейтральным с точки зрения потребления памяти, но все же быстрее.