2013-10-18 4 views
3

저는 최근에 클래스 초기화 및 초기화 프로그램 목록에서 같은 시간에 가질 수없는 것을 발견했습니다. 다음 코드는 실패클래스 초기화 및 이니셜 라이저 목록

struct s 
{ 
    int i=0;  
}; 
int main() { 
    s s1; //s1.i = 0 
    //s s2={42}; //fails 
    return 0; 
} 

내가 클래스 초기화에서 제거하면 초기화리스트는 잘 작동!

누군가 그런 이유가 허용되지 않는 이유를 설명해 줄 수 있습니까?

+1

C++ 11 모드로 컴파일 하시겠습니까? 컴파일러에 실제로 구현되어 있습니까? 어떤 컴파일러와 어떤 버전이 있습니까? –

답변

7

실제로 이것은 C++에서 허용됩니다.

struct s 
{ 
    int i=0;  
}; 

int main() { 
    s s1; 
    s s2 = {42}; // succeeds 
} 

컴파일러가 C++ 14에서 새 규칙을 구현하지 않고있는 것 같습니다. 그러나 clang의 최신 버전은 이것을 받아들이고 C++ 14 모드에서 올바른 작업을 수행합니다.

클래스 초기화가 C++ 11에 추가되었을 때 클래스가 집계되지 않도록 지정되었습니다. 이것은 당시 전체 개념이 단순하게 구성 가능해야하는 PoD 유형과 밀접하게 관련되어 있었기 때문에 수행되었습니다. 클래스 내 초기화가 있으면 유형이 더 이상 쉽게 구성 할 수 없음을 의미합니다. 그러나 그 이후로는 두 가지 개념이 더 독립적이되었고, C++ 14에서는 그 결정을 뒤집는 짧은 제안이 받아 들여졌습니다.

+0

GCC 4.8에서는 그렇지 않습니다. – thokra

+1

나는 C++ 11에서는 그것이 합법이라고 생각하지 않는다. 내 대답을 보라. – juanchopanza

+0

도 아니다 clang ++ 5.0 – chrizke

4

이 초기화 :

s s1 = { 42 }; 

s집계 것이, 또는 유효한 생성자 예컨대하는 int 또는 std::initializer_list 가지고 있어야합니다.

선언 시점에 멤버 초기화를 추가하면 클래스 s이 비 집계가되므로 더 이상 집계 초기화를 사용할 수 없습니다.

당신은 생성자를 추가하여 비 집계에 동일한 초기화 구문을 사용할 수

struct s 
{ 
    s(int i) : i(i) {} 
    int i=0;  
}; 

나는이 제한이 C++ (14)에 대한 완화 된 것으로 판단.

자세한 내용은 What are aggregates...을 참조하십시오.

+0

설명이 아닙니다. 문제는 집계가 멤버에 대해 중괄호 또는 동등한 초기화자가없는 이유입니다. –

+0

@VladfromMoscow 표준에서 그렇게 말하기 때문입니다. 거기에는 아무런 설명도 없지만 사람들은 C++에 대해이 규칙을 버리는 것이 안전하다는 것을 깨달았습니다. – juanchopanza

+0

나는이 해결 방법을 찾아 왔지만 정확하게 피하고자했던 것이었다. – Davidbrcz