static
클래스에서 데이터 멤버를 초기화 할 수없는 이유는 무엇 입니까?
C ++ 표준에서는 정적 상수 정수 또는 열거 유형 만 클래스 내에서 초기화 할 수 있습니다. 이것이 a
다른 것들은 초기화되지 않고 초기화가 허용 되는 이유 입니다.
참조 :
C ++ 03 9.4.2 정적 데이터 멤버
§4
정적 데이터 멤버가 const 정수 또는 const 열거 형인 경우 클래스 정의의 선언은 정수 상수 표현식 (5.19)이 될 상수 초기화 프로그램을 지정할 수 있습니다. 이 경우 멤버는 정수 상수 식에 나타날 수 있습니다. 멤버는 프로그램에서 사용되는 경우 네임 스페이스 범위에서 정의되어야하며 네임 스페이스 범위 정의에는 이니셜 라이저가 포함되지 않아야합니다.
정수 유형이란 무엇입니까?
C ++ 03 3.9.1 기본 유형
§7
bool, char, wchar_t 유형과 부호있는 정수 유형과 부호없는 정수 유형을 총칭하여 정수 유형이라고합니다 .43) 정수 유형의 동의어는 정수 유형입니다.
각주:
43) 따라서 열거 형 (7.2)은 정수가 아닙니다. 그러나 열거 형은 4.5에 지정된대로 int, unsigned int, long 또는 unsigned long으로 승격 될 수 있습니다.
해결 방법 :
열거 형 트릭 을 사용 하여 클래스 정의 내에서 배열을 초기화 할 수 있습니다 .
class A
{
static const int a = 3;
enum { arrsize = 2 };
static const int c[arrsize] = { 1, 2 };
};
표준이 이것을 허용하지 않는 이유는 무엇입니까?
Bjarne은 여기에서 이것을 적절하게 설명합니다 .
클래스는 일반적으로 헤더 파일에서 선언되고 헤더 파일은 일반적으로 많은 변환 단위에 포함됩니다. 그러나 복잡한 링커 규칙을 피하기 위해 C ++에서는 모든 개체에 고유 한 정의가 있어야합니다. C ++에서 객체로 메모리에 저장해야하는 엔티티의 클래스 내 정의를 허용하면 해당 규칙이 깨집니다.
static const
정수 유형 및 열거 형 만 클래스 내 초기화가 허용되는 이유는 무엇 입니까?
이에 대한 답은 Bjarne의 인용문에 숨겨져 있습니다.
"C ++에서는 모든 객체에 고유 한 정의가 있어야합니다. C ++에서 객체로 메모리에 저장해야하는 엔티티의 클래스 내 정의를 허용하면 해당 규칙이 깨질 것입니다."
단지 참고 static const
정수가 컴파일시 상수로 취급 될 수있다. 컴파일러는 정수 값이 언제든지 변경되지 않으므로 자체 마법을 적용하고 최적화를 적용 할 수 있다는 것을 알고 있습니다. 컴파일러는 이러한 클래스 멤버를 인라인하기 만하면됩니다. 즉, 더 이상 메모리에 저장되지 않으므로 메모리에 저장해야 할 필요성이 제거됩니다. , Bjarne이 언급 한 규칙에 대한 예외를 이러한 변수에 제공합니다.
여기서 주목할 점은 static const
적분 값이 In-Class Initialization을 가질 수 있더라도 이러한 변수의 주소를 가져 오는 것은 허용되지 않습니다. 클래스 밖의 정의가있는 경우에만 정적 멤버의 주소를 가져올 수 있습니다.
열거 형의 값을 정수가 예상되는 곳에 사용할 수 있기 때문에 열거 형이 허용됩니다. 위의 인용 참조
이것이 C ++ 11에서 어떻게 변경됩니까?
C ++ 11은 제한을 어느 정도 완화합니다.
C ++ 11 9.4.2 정적 데이터 멤버
§3
정적 데이터 멤버가 const 리터럴 유형 인 경우 클래스 정의의 선언 은 할당 식인 모든 initializer-clause 가 상수 식인 중괄호 또는 같음 이니셜 라이저 를 지정할 수 있습니다 . 리터럴 유형의 정적 데이터 멤버는 클래스 정의에서 선언 될 수 있습니다. 그렇다면 해당 선언 은 할당 표현식 인 모든 initializer-clause 가 있는 중괄호 또는 같음 이니셜 라이저 를 지정해야합니다.constexpr specifier;
상수 표현식입니다. [참고 :이 두 경우 모두 멤버가 상수 표현식으로 나타날 수 있습니다. —end note] 멤버는 프로그램에서 사용되는 경우 네임 스페이스 범위에서 정의되어야하며 네임 스페이스 범위 정의에는 이니셜 라이저가 포함되지 않아야합니다.
또한, C ++ 11 것이다 가 선언되는 경우 비 정적 데이터 부재 (동급) 초기화되도록 (§12.6.2.8)을 허용한다. 이것은 훨씬 쉬운 사용자 의미를 의미합니다.
이러한 기능은 아직 최신 gcc 4.7에서 구현되지 않았으므로 여전히 컴파일 오류가 발생할 수 있습니다.