Какой метод работы с флагами является предпочтительным? - PullRequest
0 голосов
/ 27 сентября 2019

Я знаю, что в C ++ есть несколько способов реализации флагов, таких как std::bitset<>, bool и использование целочисленных типов, таких как uint8_t.Но когда время выполнения или память ограничены, каков предпочтительный метод реализации флагов в C ++, например for(;;) против while(1)
Я предполагаю, что использование bool или char быстрее, чем std::bitset<>, потому что std::bitset не является базовым типом данных.

std::bitset<2> flag;
flag.reset(0);
flag.set(1);
if(flag.test(0)){...}
if(!flag.test(1)){...}
//------------------------
bool flag0 = 0;
bool flag1 = 1;
if(flag0){...}
if(!flag1){...}
//------------------------
uint8_t flag = 0b00000010;
if(flag & 0x01){...}
if(!flag & 0x02){...}

Я бы лично использовал uint8_t при работе с флагами в struct или если бы они использовались многократно во время выполнения программы, например, статус игрокаэффекты и bool для краткосрочных флагов, например, при формировании пузырьковой сортировки.
Существуют ли другие, более эффективные или более предпочтительные способы реализации флагов?

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

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

class A {
    //...

    struct {   //note: unnamed struct
        bool bCondA : 1;
        bool bCondB : 1;
        bool bCondC : 1;
        //... and so on...

    };
    //...
};


void funcA(){

    A objA;
    if(A.bCondB){
        //...
    }
    else if (A.bCondC){
        //...
    }

}

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

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

class A {
    //...
    union {   //note: unnamed union
        struct {   //note: unnamed struct
            bool m_bCondA : 1;
            bool m_bCondB : 1;
            bool m_bCondC : 1;
            //... and so on...

        };
        int m_bAllFlags;   //note: you can change int to int8_t or any type that will fit all the flags.
    };

    void methodX(); //method for testing.
    void clearFlags(){ m_bAllFlags = 0; } //clear all flags in 1 swoop.
    void clearGroup1Flags(){ m_bAllFlags & ~0b0110101101; }
    //...
};


void A::methodX(){

    A objA;

    objA.m_bCondC = true;

    if(objA.m_bCondA){
        //...
    }
    else if (objA.m_bCondA){
        //...
    }

    objA.clearFlags();

}   

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

0 голосов
/ 27 сентября 2019

Стандартный тип данных для битов («флагов») равен bool.

Если вам нужен массив битов фиксированного размера, используйте std::bitset.Если вам нужен массив битов переменного размера, используйте std::vector<bool> (но будьте осторожны: на самом деле это не std::vector, то есть не соответствует стандартному интерфейсу контейнера).Они оба упаковывают биты, поэтому они используют минимальное количество памяти, но могут быть не самыми быстрыми.И то и другое обычно удобнее, чем упаковывать биты в целые числа и использовать побитовые операторы, такие как

uint8_t flag = 0b00000010;
if(flag & 0x01){...}

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

struct Flags
{
   unsigned f1 : 1;
   unsigned f2 : 1;
   //....
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...