중요하지 않은 생성자로 유니온 초기화
멤버를 0으로 초기화하는 사용자 지정 생성자를 만드는 구조가 있습니다. 이전 컴파일러에서 릴리스 모드에서 memset을 0으로하지 않고 값이 초기화되지 않는 것을 보았습니다.
이제이 구조를 공용체에서 사용하고 싶지만 사소하지 않은 생성자가 있기 때문에 오류가 발생합니다.
그래서, 질문 1입니다. 기본 컴파일러 구현 생성자는 구조의 모든 멤버가 null 초기화되도록 보장합니까? 사소하지 않은 생성자는 깨끗한 구조를 보장하기 위해 모든 멤버의 memset을 '0'으로 만듭니다.
질문 2 : 생성자가 기본 구조에 지정되어야하는 경우 해당 요소를 포함하고 0으로 초기화 된 기본 요소를 보장하도록 공용체를 구현할 수있는 방법은 무엇입니까?
질문 1 : 기본 생성자는 C ++ 표준에 따라 POD 멤버를 0으로 초기화합니다. 아래 인용 된 텍스트를 참조하십시오.
질문 2 : 생성자가 기본 클래스에 지정되어야하는 경우 해당 클래스는 공용체의 일부가 될 수 없습니다.
마지막으로 공용체에 대한 생성자를 제공 할 수 있습니다.
union U
{
A a;
B b;
U() { memset( this, 0, sizeof( U ) ); }
};
Q1 :
C ++ 03, 12.1 생성자, 190 페이지
암시 적으로 정의 된 기본 생성자는 빈 mem-initializer-list (12.6.2) 및 빈 함수 본문을 사용하여 해당 클래스에 대해 사용자가 작성한 기본 생성자가 수행 할 클래스 초기화 집합을 수행합니다.
C ++ 03에서 8.5 이니셜 라이저, 145 페이지
T 유형의 객체를 기본 초기화한다는 것은 다음을 의미합니다.
- T가 비 POD 클래스 유형 (절 9)이면 T에 대한 기본 생성자가 호출됩니다 (T에 액세스 가능한 기본 생성자가 없으면 초기화 형식이 잘못됨).
- T가 배열 유형이면 각 요소는 기본값으로 초기화됩니다.
- 그렇지 않으면 객체는 0으로 초기화 됩니다.
T 유형의 개체를 0으로 초기화한다는 것은 다음을 의미합니다.
- T가 스칼라 유형 (3.9)이면 객체는 T로 변환 된 0 (영) 값으로 설정됩니다.
- T가 비 유니온 클래스 유형이면 각 비 정적 데이터 멤버 및 각 기본 클래스 하위 개체는 0으로 초기화됩니다 .
- T가 공용체 유형이면 개체의 첫 번째 명명 된 데이터 멤버는 0으로 초기화됩니다.
- T가 배열 유형이면 각 요소는 0으로 초기화됩니다.
- T가 참조 유형이면 초기화가 수행되지 않습니다.
2 분기 :
C ++ 03, 12.1 생성자, 190 페이지
생성자는 암시 적으로 선언 된 기본 생성자이고 다음과 같은 경우 사소한 것입니다.
- 해당 클래스에는 가상 기능 (10.3) 및 가상 기본 클래스 (10.1)가 없습니다.
- 클래스의 모든 직접 기본 클래스에는 간단한 생성자가 있습니다.
- 클래스 유형 (또는 배열) 인 클래스의 모든 비 정적 데이터 멤버에 대해 이러한 각 클래스에는 간단한 생성자가 있습니다.
C ++ 03, 9.5 Unions, 162 페이지
공용체는 멤버 함수 (생성자 및 소멸자 포함)를 가질 수 있지만 가상 (10.3) 함수는 가질 수 없습니다. 공용체에는 기본 클래스가 없어야합니다. 공용체는 기본 클래스로 사용되지 않습니다. 중요하지 않은 생성자 (12.1), 중요하지 않은 복사 생성자 (12.8), 중요하지 않은 소멸자 (12.4) 또는 중요하지 않은 클래스의 객체 복사 할당 연산자 (13.5.3, 12.8)는 공용체의 구성원이 될 수 없으며 이러한 개체의 배열이 될 수도 없습니다.
C ++ 11에서는 상황이 더 좋아졌습니다.
이제 Stroustrup 자신 이 설명한대로 합법적으로이를 수행 할 수 있습니다 ( C ++ 11 의 Wikipedia 기사 에서 해당 링크에 도달했습니다 ).
Wikipedia의 예는 다음과 같습니다.
#include <new> // Required for placement 'new'.
struct Point {
Point() {}
Point(int x, int y): x_(x), y_(y) {}
int x_, y_;
};
union U {
int z;
double w;
Point p; // Illegal in C++03; legal in C++11.
U() {new(&p) Point();} // Due to the Point member, a constructor
// definition is now *required*.
};
Stroustrup은 좀 더 자세히 설명합니다.
AFAIK 공용체 구성원은 생성자 또는 소멸자를 가질 수 없습니다.
질문 1 : 아니요, 그런 보장은 없습니다. 생성자의 초기화 목록에없는 모든 POD 멤버는 기본값으로 초기화되지만 사용자가 정의한 생성자와 함께 초기화 목록이 있습니다. 생성자를 정의하지 않거나 초기화 목록과 빈 본문없이 생성자를 정의하면 POD 멤버가 초기화되지 않습니다.
비 -POD 멤버는 항상 기본 생성자를 통해 구성되며, 합성되면 다시 POD 멤버를 초기화하지 않습니다. 유니온 멤버에 생성자가 없을 수 있다는 점을 감안할 때 유니온에서 구조체의 POD 멤버는 초기화되지 않을 것입니다.
질문 2 : 항상 다음과 같이 구조 / 결합을 초기화 할 수 있습니다.
struct foo
{
int a;
int b;
};
union bar
{
int a;
foo f;
};
bar b = { 0 };
unwesen 의 게시물에 대한 Greg Rogers의 의견에서 언급했듯이 조합에 생성자 (원하는 경우 소멸자)를 제공 할 수 있습니다.
struct foo
{
int a;
int b;
};
union bar
{
bar() { memset(this, 0, sizeof(*this)); }
int a;
foo f;
};
이런 식으로 할 수 있습니까?
class Outer
{
public:
Outer()
{
memset(&inner_, 0, sizeof(inner_));
}
private:
union Inner
{
int qty_;
double price_;
} inner_;
};
... 아니면 이런 건가요?
union MyUnion
{
int qty_;
double price_;
};
void someFunction()
{
MyUnion u = {0};
}
이를 얻으려면 컴파일러가 C ++ 0x를 지원할 때까지 기다려야합니다. 그때까지는 죄송합니다.
참조 URL : https://stackoverflow.com/questions/321351/initializing-a-union-with-a-non-trivial-constructor
'programing' 카테고리의 다른 글
jQuery를 JSfiddle에 추가하는 방법 (0) | 2021.01.15 |
---|---|
렌더링 기능 외부에서 React Context에 액세스 (0) | 2021.01.15 |
아카이브 내 랜덤 액세스를 잘 지원하는 압축 형식? (0) | 2021.01.15 |
JavaScript에서 void 연산자의 요점은 무엇입니까? (0) | 2021.01.15 |
C ++의 sizeof는 컴파일 타임이나 런타임에 평가됩니까? (0) | 2021.01.15 |