C ++에서 비트 필드 구조물을 초기화하는 가장 좋은 방법은 무엇입니까?
-
03-07-2019 - |
문제
C ++에는 익명의 비트 필드 구조물이 포함 된 수업이 있습니다. 모든 필드를 수동으로 작성하지 않고도 0으로 초기화하고 싶습니다.
초기화를 세 곳에 두는 것을 상상할 수 있습니다.
- 비트 필드에서 생성자를 만듭니다
- 포함 된 클래스 생성자의 이니셜 라이저 목록에서 0
- 포함 된 클래스의 생성자 본체에서 제로 아웃
이 비트 필드에는 많은 분야가 있으며, 모두 나열하지는 않습니다.
예를 들어 다음 코드를 참조하십시오.
class Big {
public:
Big();
// Bitfield struct
struct bflag_struct {
unsigned int field1 : 1;
unsigned int field2 : 2;
unsigned int field3 : 1;
// ...
unsigned int field20 : 1;
// bflag_struct(); <--- Here?
} bflag;
unsigned int integer_member;
Big *pointer_member;
}
Big::Big()
: bflag(), // <--- Can I zero bflag here?
integer_member(0),
pointer_member(NULL)
{
// Or here?
}
이들 중 하나가 선호됩니까? 아니면 내가 놓친 다른 것이 있습니까?
편집 : 아래에 허용 된 답변을 기반으로 (Ferruccio) 나는이 솔루션을 해결했습니다.
class Big {
// ...
struct bflag_struct {
unsigned int field 1 : 1;
// ...
bflag_struct() { memset(this, 0, sizeof *this); };
}
// ...
}
해결책
당신은 항상 당신의 생성자에서 이것을 할 수 있습니다 :
memset(&bflag, 0, sizeof bflag);
다른 팁
비트 필드 구조물을 조합하여 0으로 초기화하기 쉬운 것.
필드에 액세스 할 때 추가 수준의 간접 수준을 추가 할 수는 있지만 노조를 사용할 수 있습니다.
class Big {
union {
struct {
unsigned int field1 : 1;
...
} fields;
unsigned int all_fields;
};
...
};
Big::Big()
: all_fields(0),
...
{
...
}
MSVC는 노조 내부의 익명 구조를 허용합니다 (예 :의 정의 참조 D3DMATRIX
안에 <d3d9.h>
), 그러나 이것은 비표준 C ++ 확장으로 가능하면 사용하지 않아야합니다.
제쳐두고, 일부 레거시 코드를 인터페이스하기 위해 비트 필드가 필요하지 않으면 사용해서는 안됩니다. 그것들은 본질적으로 무의식 할 수없고 비효율적입니다.
함수와 같은 이니셜 라이저 ( "여기에"제로 BFLAG가 있습니까? ")를 사용하면 0 값으로 포드 구조물을 초기화하기에 충분한 100%입니다.
이와 관련하여 컴파일러가 고장났다는 것을 알지 못하면 해당 멤버의 추가 초기화를 수행하면 이점이없는 이점을 두 번 초기화합니다.
편집 : 'Fun'을 위해서는 VS2005, VS2008, GCC 3.4.4, GCC 4.2 및 Borland C ++ 5.5.1로 이것을 확인했습니다. Borland C ++ 5.5.1 만 잘못됩니다.
그리고 표준의 8.5와 8.5.1은 기능과 유사한 이니셜 라이저가 포드 구조물을 제로 인트해야한다는 것을 암시하기 때문에 '잘못'이라고 말합니다.
생성자의 Zeromemory 또는 memset을 사용하여 메모리를 제로화 할 수 있습니다.