C++: Можно ли сжимать объекты bool в одном байте?

Рассмотрим класс с несколькими атрибутами bool

class A
{
  bool a;
  bool b;
  bool c;
  bool d;
  bool e;
  bool f;
};

Хотя каждый объект bool может быть представлен одним битом, здесь каждый атрибут будет принимать байт (если я не ошибаюсь). Объект займет 6 байтов вместо 1 байта (6 бит из которых фактически будут использоваться). Причина в том, что биты не адресуются, только байты.

Чтобы немного сжать память, можно использовать vector<bool> или bitset, а затем обращаться к атрибутам по их индексам. Например, можно написать функцию get как

bool A::get_d() {data[3];}

В идеале мне бы хотелось иметь прямой доступ к атрибутам с помощью InstanceOfA.d. Можно ли это сделать, убедившись, что все мои 6 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
10
0
214
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Вы можете использовать битовые поля. Работает с Repl.it gcc версии 4.6.3.

#include <iostream>

struct Test 
{
  bool a:1;
  bool b:1;
  bool c:1;
  bool d:1;
  bool e:1;
  bool f:1;
  bool g:1;
  bool h:1;
  //bool i:1; //would increase size to 2 bytes.
};

int main()
{
  Test t;
  std::cout << sizeof(t) << std::endl;
  return 0;
}

Именно то, что я искал! Спасибо! Я приму ответ, когда смогу.

Remi.b 13.12.2018 01:15

Другая альтернатива - std::bitset.

Eljay 13.12.2018 01:25

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

Pete Becker 13.12.2018 02:00

Если вы действительно заботитесь об экономии места, вам, вероятно, следует использовать bitset вместо битового поля.

Вы можете увидеть этот ответ для полного сравнения, но, по сути, битовое поле будет иметь некоторые накладные расходы из-за того, что оно является структурой, и компилятор может или не может фактически упаковывать элементы вместе, чтобы сэкономить место.

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

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

std::bitset<8> bacon;
bacon.set();    // 11111111
bacon.reset(1); // 11111101 Note: counts index from the right

std::bitset<4> fancy (std::string("1111"));
fancy[1] = 0;      // 1101 Note: counts index from the right
fancy.test(1) == 0 // true

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