Когда использовать битовые наборы STL вместо отдельных переменных?

В какой ситуации мне было бы более целесообразно использовать битовый набор (контейнер STL) для управления набором флагов, а не объявлять их как несколько отдельных (bool) переменных?

Получу ли я значительный прирост производительности, если буду использовать битовый набор для 50 флагов вместо 50 отдельных переменных типа bool?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
15
0
9 698
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Итак, 50 bools в качестве битового набора займут 7 байтов, а 50 bools в качестве bools займут 50 байтов. В наши дни это не так уж и важно, поэтому использование bools, вероятно, нормально.

Однако есть одно место, где битовый набор может быть полезен, - это если вам нужно много передавать эти bools, особенно если вам нужно вернуть набор из функции. Используя битовый набор, вы получаете меньше данных, которые нужно перемещать в стеке для возврата. Опять же, вы можете просто использовать refs и иметь еще меньше данных для передачи. :)

В отдельном случае с bool вы можете использовать битовое поле, чтобы не тратить впустую 50 байтов.

Isaac Pascual 01.02.2018 20:18

Это зависит от того, что вы подразумеваете под «приростом производительности». Если вам нужно всего 50 из них, и у вас не мало памяти, тогда отдельные bools почти всегда лучший выбор, чем bitset. Они займут больше памяти, но булы будут намного быстрее. Битовый набор обычно реализуется как массив целых чисел (логические значения упаковываются в эти целые числа). Таким образом, первые 32 bool (бита) в вашем битовом наборе будут занимать только один 32-битный int, но для чтения каждого значения вам нужно сначала выполнить несколько побитовых операций, чтобы замаскировать все значения, которые вам не нужны. Например. чтобы прочитать 2-й бит битового набора, вам необходимо:

  1. Найдите int, который содержит нужный бит (в данном случае это первый int)
  2. Побитовое И это int с '2' (т.е. значение & 0x02), чтобы узнать, установлен ли этот бит

Однако, если память является узким местом и у вас много bools, использование битового набора может иметь смысл (например, если ваша целевая платформа - мобильный телефон или это какое-то состояние в очень загруженной веб-службе)

ПРИМЕЧАНИЕ: std :: vector для bool обычно имеет специализацию для использования эквивалент битового набора, что делает его намного меньше и медленнее по тем же причинам. Поэтому, если скорость является проблемой, вам лучше использовать вектор char (или даже int) или даже просто использовать массив bool старой школы.

RE @Wilka:

На самом деле битовые наборы поддерживаются C / C++ таким образом, что вам не нужно делать собственное маскирование. Я не помню точного синтаксиса, но это примерно так:

struct MyBitset {
  bool firstOption:1;
  bool secondOption:1;
  bool thirdOption:1;
  int fourBitNumber:4;
};

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

MyBitset bits;
bits.firstOption = true;
bits.fourBitNumber = 2;

if (bits.thirdOption) {
  // Whatever!
}

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

std :: bitset даст вам дополнительные очки, когда вам нужно сериализовать / десериализовать его. Вы можете просто записать его в поток или прочитать с его помощью. Но, конечно, отдельные буллы будут быстрее. В конце концов, они оптимизированы для такого использования, в то время как битовый набор оптимизирован для пространства и по-прежнему задействует вызовы функций. Это никогда не будет быстрее, чем отдельные буллы.

Bitset

  • Очень эффективное использование пространства
  • Менее эффективен из-за возни с битами
  • Обеспечивает сериализацию / десериализацию с помощью op<< и op>>
  • Все биты упакованы вместе: у вас будут флаги в одном месте.

Отдельные буллы

  • Очень быстро
  • Булы не упаковываются вместе. Они где-то будут членами.

Определитесь с фактами. Лично я бы использовал std::bitset для некоторых критических проблем, не связанных с производительностью, и использовал бы bools, если у меня либо всего несколько bool (и, следовательно, он вполне доступен для обзора), либо если мне нужна дополнительная производительность.

Я бы добавил возможность использования побитового оператора или для комбинирования наборов флагов в качестве огромного выигрыша для битового набора.

Greg Rogers 19.11.2008 07:58

Другие вопросы по теме