2009-04-21 3 views
8

이의 나가로 정의 된 구조체가 있다고 가정하자 :C++에서 중괄호를 사용하여 객체를 인스턴스화한다는 것은 무엇을 의미합니까?

typedef 
struct number{ 
    int areaCode; 
    int prefix; 
    int suffix; 
} PhoneNumber; 

나는이 구조체의 인스턴스를 생성, 나는 다음과 같은 구문을 사용하는 경우 :

PhoneNumber homePhone = {858, 555, 1234}; 

... 그것은 생성자를

를 호출을? 기본 생성자 또는 복사 생성자 또는 'new'를 호출하지 않기 때문에 전혀 생성자가 없습니다.

이 질문의 진정한 목적은 네 번째 필드를 추가하는 방법을 찾는 것입니다.

PhoneNumber officePhone = {858, 555, 6789, 777} 

그러나, 이미 만든이 PHONENUMBER 인스턴스의 수백 : 그래서 지금

typedef 
struct number{ 
    int areaCode; 
    int prefix; 
    int suffix; 
    int extension; // NEW FIELD INTRODUCED 
} PhoneNumber; 

, 나는 네 개의 필드와 함께 새로운 PHONENUMBER 개체를 만들 수 있습니다 : 그래서 나는 나의 구조체를 다시 정의 할 3 개의 필드 (xxx, xxx, xxxx) 만 있습니다. 따라서 이미 정의 된 PhoneNumber 객체의 모든 단일 인스턴스화를 검토하고 수정하고 싶지는 않습니다. 나는 혼자 남겨 둘 수 있기를 원하지만 4 개 필드로 새 전화 번호 인스턴스를 만들 수 있어야합니다. 그래서 기존의 세 매개 변수 인스턴스화가 중단되지 않도록 생성자를 덮어 쓰는 방법을 알아 내려고 노력하고 있지만 새 매개 변수 인스턴스화도 지원합니다.

3 필드를 사용하고 네 번째를 기본값 '0'으로 설정하는 재정의 기본 생성자를 정의하려고하면 생성자 정의가 아닌 인스턴스화 부분에서 오류가 발생합니다. {...}이 아닌 생성자에 의해 초기화되어야합니다. 따라서 기본 생성자를 재정의하면 더 이상 중괄호를 사용하여 새 객체를 만들 수 없습니다.

죄송합니다. 원래의 질문에서 완전히 벗어나면 죄송합니다.

+0

관련 : [http://stackoverflow.com/questions/88957/what-does-0-mean-in-c/88960#88960](http://stackoverflow.com/questions/ 88957/what-does-0-mean-in-c/88960 # 88960) –

답변

1

효과적으로 기본 ctor를 호출합니다. 무슨 일이 일어나고 있는지는 구조체가 할당되어 있고 각 값은 기본값 "="이 할당되어 있습니다.

+0

기본 생성자가 호출되지 않고 operator =도 호출되지 않습니다. C++ 8.5.1에서는 집계 초기화를위한 구문을 정의합니다. –

+0

내가 쓴 것을 * 읽었습니까? 기본 "="은 무엇입니까? –

2

C++의 구조체는 클래스와 같습니다. 기본 생성자가 호출되고 있습니다. 그런 다음 각 필드는 할당 연산자와 함께 복사됩니다.

+0

기본 생성자가 POD 유형에 대해 호출되지 않고 필드가 복사되지 않습니다. 구문은 집계의 멤버 초기화를 정의합니다. C++ 8.5.1을 참조하십시오. –

4

구성원이 실제로 복사 초기화됩니다. 각각의 기본 생성자는 호출되지 않으며 어떤 다른 답변에서 제안하는 것과는 반대로 operator=이 포함되어 있지 않습니다. geordi이라고하는 소프트웨어로 표시 할 수도 있습니다. 또는 표준을 통해 읽을 수도 있습니다. 나는 그 소프트웨어를 사용하여 "재미있는"방법을 보여줄 것이다. 생성자/복사 생성자 또는 소멸자/복사 할당 연산자가 호출 될 때 우리에게 보여줄 수있는 클래스 tracked::B을 가지고 있습니다. 이 표시 출력은 (그것을 다음 문에 추적 TRACK 기준)이다 :이 코드

struct T { tracked::B b; }; int main() { tracked::B b; TRACK T t = { b }; } 

보시다시피을 사용

B1*(B0) B1~ 

, 두 번째 B 객체 - 지역 내 회원입니다 변수 t은 다른 개체 b에서 복사 초기화됩니다. 물론 할당 연산자가 활성화되어 있지 않습니다. 원한다면 Standard의 12.6.1/2에서 읽을 수 있습니다.

동일한 방법으로 배열 (마찬가지로 집계)에서도 마찬가지입니다. 많은 사람들은 배열의 멤버 인 객체는 기본 생성자가있는 유형을 가져야한다고 생각합니다. 그러나 그것은 사실이 아닙니다. 그들은 단지 자신의 유형의 다른 객체에 의해 초기화 된 사본 일 수 있으며 정상적으로 작동합니다.

모두 기타 요소 집합에서 명시 적으로 초기화되지 않은 요소는 값이 초기화됩니다. 값 초기화는 기본 초기화와 0 초기화가 혼합 된 것입니다. 실제로 멤버에 사용자가 생성자를 선언 한 유형이있는 경우 해당 생성자가 호출됩니다. 형식이 이 아니고 사용자가 생성자를 선언 한 경우, 그 각 멤버는 값이 초기화됩니다. 내장형 (int, bool, pointers, ...)의 경우 값 초기화는 0 초기화와 같습니다 (즉, 해당 변수가 0이됨을 의미). 다음은 제로에 각 멤버를 초기화합니다 - 하나가 될 것이다, (a)는 첫 번째 제외 :

struct T { int a, b, c; }; int main() { T t = { 1 }; } 

그 초기화 규칙은 참으로 무서운 - C++의 2003 년 개정은 그 값 초기화를 도입, 특히 때문이다. 그것은 wasn't part of the Standard부터 1998 년까지입니다. 그 중괄호로 둘러싸인 초기화에 더 관심이 있다면 How to initialize nested structures in C++?을 읽을 수 있습니다.

3

다른 사람이 작성한 것처럼 기본 ctor을 호출하지 않습니다. 개념적으로는 같지만 실제로는 어셈블리 코드에서 함수 호출을 찾을 수 없습니다.

대신 멤버는 초기화되지 않은 상태로 유지됩니다. 중괄호로 초기화하고 있습니다.

흥미롭게

이이 어셈블리

PhoneNumber homePhone = {858, 555, 1234}; 

결과 (GCC 4.0.1, -O0) :이

movl $858, -20(%ebp) 
movl $555, -16(%ebp) 
movl $1234, -12(%ebp) 

많지 않습니다 놀라움. 어셈블리는 위의 C++ 문을 포함하는 함수를 인라인합니다. 값 ($로 시작)은 스택으로의 오프셋 (ebp 레지스터)으로 이동합니다 (movl). 구조체 멤버의 메모리 위치가 초기화 코드보다 우선하기 때문에이 값은 음수입니다.

완전히 구조체를 초기화하지 않는 경우, 즉 일부 구성원과 같이 생략 :

movl $0, -20(%ebp) 
movl $0, -16(%ebp) 
movl $0, -12(%ebp) 
movl $858, -20(%ebp) 
movl $555, -16(%ebp) 

것처럼 보인다 : 나는 다음과 같은 어셈블리 코드를 얻을 ...

PhoneNumber homePhone = {858, 555}; 

컴파일러는 실제로 기본 생성자를 호출하는 것과 매우 비슷한 무언가를 수행 한 다음 할당합니다. 그러나 이것은 함수 호출이 아닌 호출 함수에서 인라인입니다.

다른 한편으로는, 주어진 값으로, 멤버를 초기화과 같이 기본 생성자를 정의하는 경우 :

struct PhoneNumber { 
    PhoneNumber() 
    : areaCode(858) 
    , prefix(555) 
    , suffix(1234) 
    { 
    } 

    int areaCode; 
    int prefix; 
    int suffix; 
}; 

PhoneNumber homePhone; 

그럼 당신은 실제로 함수를 호출하고, 데이터 멤버를 초기화 어셈블리 코드를 얻을 수를 구조체 포인터들을 통해

movl 8(%ebp), %eax 
movl $858, (%eax) 
movl 8(%ebp), %eax 
movl $555, 4(%eax) 
movl 8(%ebp), %eax 
movl $1234, 8(%eax) 

구조체의 데이터의 처음 movl 8(%ebp), %eax 세트 포인터 값 (EAX 레지스터)를 진행 각 라인. 다른 라인에서는 앞의 두 예제에서 직접 스택 어드레싱과 유사한 eax가 오프셋 4와 오프셋 8로 직접 사용됩니다. 물론이 모든의

컴파일러 구현에 특정하지만, 다른 컴파일러는 매우 다른 무언가를 한 경우에 나는 놀랠 것입니다.

+0

최적화가 시작되면 멤버 초기화 목록과 함께 기본 생성자를 사용하여 포인터 역 참조를 생성합니까? 나는. gcc에서 -O3 옵션으로 컴파일하면 포인터 역 참조가 제거됩니까? – paxos1977

+0

컴파일러 출력을 보면 사양을 이해할 수 없습니다. –

+0

@ceretullis : 나는 보지 않았다. @ don.neufeld : 동의했는데 실제로 일어난 일을 이해하는 데 쓸모가 없다는 의미는 아닙니다. –

0

그러나, 나는이 PHONENUMBER 인스턴스 수백 이미 단지 3 필드 을 만들었습니다 (XXX, XXX, XXXX). 그래서 나는 통과하고 정의 가 이미 내 PHONENUMBER 개체의 모든 단일 인스턴스를 수정하지 않습니다.

아니 문제는, 그냥 신경 끄시 고, 갱신 인스턴스-에 대한 재정의 수준의 어 ..... 및 호출합니다. 이 "인정합니다"표시로 진행

2

초기화는 적어도 나에게,이다, C++ 표준의 가장 어려운 부분 중 하나. 사용중인 구문은 다음과 같습니다. Aggregate x = { 1, 2, 3, 4 };은 처음 4 명의 구성원이 1, 2, 3 및 4 값을 할당 한 집계 유형의 초기화를 정의합니다.

구조체가 3에서 4로 증가했습니다) 중괄호 사이의 초기화 목록에없는 필드는 값이으로 초기화됩니다. 특히 스칼라 유형의 경우 제로 초기화은 0을 할당하는 것과 같습니다. 따라서 네 번째 요소가 초기화됩니다 0에

참고

C++ 표준, 8.5 장,보다 정확하게 8.5.1 집합에 모두 정의되어 있습니다. 집계는 암시 적으로 선언 된 기본 생성자로 초기화되지 않습니다. 위의 구문을 사용하면 제공된 값으로 주어진 필드를 초기화하도록 컴파일러에 요청하는 것입니다. 집계의 모든 여분의 필드 유형은 생성자를 가진 클래스 인 경우 값이 이제 값 초기화는 사용자 정의 기본 생성자의 호출로 정의된다

를 초기화해야한다. 그것은 사용자 정의 생성자없이 배열 또는 비 연합 클래스이면 부재 특성의 각 값 을 초기화 할 것이다. 그렇지 않으면 목적 제로 다시 정의된다 ...

제로 초기화 스칼라 유형의 값을 0으로 설정하는 것으로 정의된다를 초기화 할 것이다. 클래스의 경우 각 클래스 데이터 멤버와 기본 클래스는 으로 초기화되며으로 초기화됩니다.노조를 들어, 첫 번째 회원 (만) 배열의 모든 구성원이 제로을 초기화됩니다 제로, 초기화 될 것입니다.

0

관련된 당신의 유형에 생성자가 없기 때문에 기존의 세 매개 변수 구문 집계 초기화 사이트에서 수정 될 필요가있을 것이다.

새로 추가 된 필드의 의미가 아니라면 (ie. 그 새로운 필드 유형, 당신에게, (관용구 디자인 가이드 라인 넌센스에 .NET 프로그래밍, 브래드와 공동 등 추천)

'를 디자인 인식 제로화'하는

는 할 수 없습니다 :

A) 중 C와 같은 의미있는 무언가를 제공합니다 ++ 마법에 참여하는 방법이 있다면 기본 매개 변수는

(deault/옵션 PARAMS 곧 옛 COM 식료품 웹 4.0 근처에 대중 시장 C#을 상점에서 사용할 수) 없으며

b)에 따를 수 있습니다 무효 값 마커가 0 인 값 유형을 디자인하는 패턴과 비슷한 C# 패턴 (이 경우 틀림없이 v 나쁜 점은 일반적으로 상수를 제어 할 수 없다는 것입니다. 소스 레벨 라이브러리가 매우 잘하고 모든 JavaTM MS와 유사한 프레임 워크가 실패합니다. 한마디로

, 0 대부분의 컴파일러 작가가 모든 관리 스타일이나 관용구 적 존재 이전과 유용한 보았다 유효한 당신이 박제 가치와 어떤 경우는 그러나 그것은 꼭 맞는 것은 아닙니다.

어쨌든, 가장 좋은 기회는 C++ 또는 C#을하지 않습니다. 즉, 코드 생성입니다. 현대의 C++보다 더 자유로운 메타 프로그래밍 "templating"이 푸시됩니다. JSON 배열 주석과 비슷한 것을 알 수 있으며, 정신을 사용하거나 (내 조언은) 자신의 util을 롤업 할 수 있습니다. 장기적으로는 도움이됩니다. 결국에는 더 잘하기를 원할 것입니다. (즉, .NET에서 오슬로 (Oslo) 모델링이라고 부르는 사람들). 그런

[문제 모두 많은 언어에 걸쳐있는 모든 C 스타일의 사람의 그것의 단점 (C, C++, 자바, C#을, 당신은 그것을 이름); 어떤 유형의 크로스 도메인이나 의미 론적 I/O 작업에 필요한 배열 hackery의 배열과 매우 유사하며 SOAP 같은 웹 기술에서도 분명합니다. 새로운 C++ 0x 가변 비트는 여기서도 많이 도움이되지는 않지만 분명히 있습니다. 일부 서식 파일 해커를 사용하기로 선택한 경우 기하 급수적으로 빠른 컴파일 시간을 가져옵니다. :)] 관심

관련 문제