your programing

기본값, 값 및 제로 초기화 혼란

lovepro 2020. 10. 8. 08:24
반응형

기본값, 값 및 제로 초기화 혼란


값 및 기본값 및 제로 초기화에 대해 매우 혼란 스럽습니다. 특히 다른 표준 C ++ 03C ++ 11 (및 C ++ 14 ) 을 위해 시작될 때 .

나는 누군가가 도움을 줄 수 있다면 많은 사용자에게 도움이 될 것이므로 더 일반적으로 만들기 위해 Value- / Default- / Zero- Init C ++ 98C ++ 03 정말 좋은 답변을 인용하고 확장하려고 합니다. 언제 어떤 일이 발생하는지에 대한 좋은 개요를 얻기 위해 필요한 간격

한마디로 예제를 통한 전체 통찰력 :

때로는 new 연산자에 의해 반환 된 메모리가 초기화되고, 때로는 새로 만드는 유형이 POD (일반 이전 데이터) 인지 또는 POD 멤버를 포함하고있는 클래스 인지 여부에 따라 초기화되지 않을 수 있습니다. 컴파일러 생성 기본 생성자.

  • 에서 1998 ++ C : 초기화의 2 종류가 있습니다 제로기본 초기화는
  • 에서 2003 ++ C 초기화의 제 3 유형의 값을 초기화가 추가되었습니다.
  • 에서 C ++ 2011 / C ++ 2014리스트 초기화를 첨가하고 규칙 부가가치 / default- / 제로 초기화가 조금 변경되었습니다.

취하다:

struct A { int m; };                     
struct B { ~B(); int m; };               
struct C { C() : m(){}; ~C(); int m; };  
struct D { D(){}; int m; };             
struct E { E() = default; int m;} /** only possible in c++11/14 */  
struct F {F(); int m;}  F::F() = default; /** only possible in c++11/14 */

C ++ 98 컴파일러에서 다음이 발생해야합니다 .

  • new A-불확실한 값 ( APOD 임)
  • new A()-제로 초기화
  • new B-기본 구성 ( B::m초기화되지 않음, BPOD가 아님)
  • new B()-기본 구성 ( B::m초기화되지 않음)
  • new C-기본 구성 ( C::m0으로 초기화 됨, CPOD가 아님)
  • new C()-기본 구성 ( C::m0으로 초기화 됨)
  • new D-기본 구성 ( D::m초기화되지 않음, DPOD가 아님)
  • new D()- 기본 구성? ( D::m초기화되지 않음)

C ++ 03 준수 컴파일러에서는 다음과 같이 작동해야합니다.

  • new A-불확실한 값 ( APOD 임)
  • new A()-value-initialize A, POD이므로 0으로 초기화됩니다.
  • new BB::m-default -initializes ( 초기화되지 B않은 상태로두고 POD가 아님)
  • new B()- 값 초기화합니다 B사용자 정의 반대로 기본 ctor에 이후의 모든 필드를 제로 - 초기화 컴파일러가 생성됩니다.
  • new CC-default -initializes , 기본 ctor를 호출합니다. ( C::m0으로 초기화 됨, CPOD가 아님)
  • new C()C-value -initializes , 기본 ctor를 호출합니다. ( C::m0으로 초기화 됨)
  • new D-기본 구성 ( D::m초기화되지 않음, DPOD가 아님)
  • new D()- 가치 초기화 D? , 기본 ctor ( D::m초기화되지 않음) 를 호출합니다.

기울임 꼴 값 및? 불확실성이 있습니다.이 문제를 해결하는 데 도움을주세요 :-)

C ++ 11 준수 컴파일러에서는 다음과 같이 작동해야합니다.

??? (여기서 시작하면 어쨌든 잘못 될 것입니다)

C ++ 14 준수 컴파일러에서는 다음과 같이 작동해야합니다. ??? (여기서 시작하면 어쨌든 잘못 될 것입니다.) (답변에 따른 초안)

  • new A-기본 초기화 A, 컴파일러 생성. ctor, ( A::m초기화되지 않은 상태) ( APOD 임)
  • new A()-값 초기화 A, [dcl.init] / 8의 2. 지점 이후 제로 초기화

  • new B-기본 초기화 B, 컴파일러 생성. ctor, ( B::m초기화되지 않은 리프 ) ( B은 POD가 아님)

  • new B()- 값 초기화합니다 B사용자 정의 반대로 기본 ctor에 이후의 모든 필드를 제로 - 초기화 컴파일러가 생성됩니다.
  • new CC-default -initializes , 기본 ctor를 호출합니다. ( C::m0으로 초기화 됨, CPOD가 아님)
  • new C()C-value -initializes , 기본 ctor를 호출합니다. ( C::m0으로 초기화 됨)
  • new D-기본 초기화 D( D::m초기화되지 않음, DPOD가 아님)
  • new D()- D기본 ctor를 호출하는 value-initializes ( D::m초기화되지 않음)
  • new E-comp E를 호출하는 default-initializes . gen. ctor. ( E::m초기화되지 않음, E는 POD가 아님)
  • new E()-값-초기화 E, [dcl.init] / 8의E 2 점 이후 0으로 초기화 됨 )
  • new F-comp F를 호출하는 default-initializes . gen. ctor. ( F::m초기화되지 않음, FPOD가 아님)
  • new F()-value -initializes F, 1부터 기본값으로 초기화 F 됩니다. [dcl.init] / 8에서 지정합니다 ( Fctor 함수는 사용자가 선언하고 첫 번째 선언에서 명시 적으로 기본값이 설정되거나 삭제되지 않은 경우 사용자가 제공합니다. Link )

C ++ 14 new는 [expr.new] / 17에서 생성 된 객체의 초기화를 지정합니다 (C ++ 11에서는 [expr.new] / 15, 그 당시에는 메모가 메모가 아니라 표준 텍스트였습니다).

새로운 표현 형식의 개체를 만들고 T다음과 같이 해당 객체를 초기화한다 :

  • 경우 새로운 초기화가 생략 된 객체는 기본 초기화 (8.5). [ 참고 : 초기화가 수행되지 않은 경우 개체에는 불확실한 값이 있습니다. — 끝 참고 ]
  • 그렇지 않으면 new-initializer직접 초기화에 대한 8.5의 초기화 규칙에 따라 해석됩니다 .

기본 초기화는 [dcl.init] / 7에 정의되어 있습니다 (C ++ 11의 경우 / 6, 단어 자체가 동일한 효과를 가짐).

유형의 객체 기본 초기화T 한다는 것은 다음을 의미합니다.

  • 경우 T에 (아마도 이력서 자격) 클래스 유형 (9 절), 기본 생성자 (12.1)이다 T(라고하며 경우 초기화가 잘못 형성되는 T디폴트 생성자 또는 오버로드 확인 (모호한 또는 13.3) 결과가 없습니다 초기화의 컨텍스트에서 삭제되거나 액세스 할 수없는 함수
  • 경우 T배열 형이며, 각 요소는 기본 초기화 ;
  • 그렇지 않으면 초기화가 수행되지 않습니다.

그러므로

  • new A단독 원인 A의 기본 생성자는 초기화하지 않는, 호출 할 수 있습니다 m. 불확실한 값. 에서 동일해야합니다 new B.
  • new A() [dcl.init] / 11 (C ++ 11의 경우 / 10)에 따라 해석됩니다.

    이니셜 라이저가 빈 괄호 세트 인 객체, 즉는 ()값이 초기화됩니다.

    And now consider [dcl.init]/8 (/7 in C++11†):

    To value-initialize an object of type T means:

    • if T is a (possibly cv-qualified) class type (Clause 9) with either no default constructor (12.1) or a default constructor that is user-provided or deleted, then the object is default-initialized;
    • if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
    • if T is an array type, then each element is value-initialized;
    • otherwise, the object is zero-initialized.

    Hence new A() will zero-initialize m. And this should be equivalent for A and B.

  • new C and new C() will default-initialize the object again, since the first bullet point from the last quote applies (C has a user-provided default constructor!). But, clearly, now m is initialized in the constructor in both cases.


† Well, this paragraph has slightly different wording in C++11, which does not alter the result:

To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
  • if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
  • if T is an array type, then each element is value-initialized;
  • otherwise, the object is zero-initialized.

The following answer extends the answer https://stackoverflow.com/a/620402/977038 which would serve as a reference for C++ 98 and C++ 03

Quoting the answer

  1. In C++1998 there are 2 types of initialization: zero and default
  2. In C++2003 a 3rd type of initialization, value initialization was added.

C++11 (In reference to n3242)

Initializers

8.5 Initializers [dcl.init] specifies that a variable POD or non POD can be initialized either as brace-or-equal-initializer which can either be braced-init-list or initializer-clause aggregately referred to as brace-or-equal-initializer or using ( expression-list ). Previous to C++11, only (expression-list) or initializer-clause was supported though initializer-clause was more restricted then what we have in C++11. In C++11, initializer-clause now supports braced-init-list apart from assignment-expression as was in C++03. The following grammar summarizes the new supported clause, where the part is bold is newly added in the C++11 standard.

initializer:
    brace-or-equal-initializer
    ( expression-list )
brace-or-equal-initializer:
    = initializer-clause
    braced-init-list
initializer-clause:
   &nbspassignment-expression
    braced-init-list
initializer-list:
    initializer-clause ...opt
    initializer-list , initializer-clause ...opt**
braced-init-list:
    { initializer-list ,opt }
    { }

Initialization

Like C++03, C++11 still supports three form of initialize


Note

The part highlighted in bold has been added in C++11 and the one that is striked out has been removed from C++11.

  1. Initializer Type:8.5.5 [dcl.init] _zero-initialize_

Performed in the following cases

  • Objects with static or thread storage duration are zero-initialized
  • If there are fewer initializers than there are array elements, each element not explicitly initialized shall be zero-initialized
  • During value-initialize, if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized.

To zero-initialize an object or reference of type T means:

  • if T is a scalar type (3.9), the object is set to the value 0 (zero), taken as an integral constant expression, converted to T;
  • if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is zero-initialized and padding is initialized to zero bits;
  • if T is a (possibly cv-qualified) union type, the object’s first non-static named data member is zero initialized and padding is initialized to zero bits;
  • if T is an array type, each element is zero-initialized;
  • if T is a reference type, no initialization is performed.

2. Initializer Type: 8.5.6 [dcl.init] _default-initialize_

Performed in the following cases

  • If the new-initializer is omitted, the object is default-initialized; if no initialization is performed, the object has indeterminate value.
  • If no initializer is specified for an object, the object is default-initialized, except for Objects with static or thread storage duration
  • When a base class or a non-static data member is not mentioned in a constructor initializer list and that constructor is called.

To default-initialize an object of type T means:

  • if T is a (possibly cv-qualified) non-POD class type (Clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
  • if T is an array type, each element is default-initialized;
  • otherwise, no initialization is performed.

Note Until C++11, only non-POD class types with automatic storage duration were considered to be default-initialized when no initializer is used.


3. Initializer Type: 8.5.7 [dcl.init] _value-initialize_

  1. When an object(nameless temporary, named variable, dynamic storage duration or non-static data member) whose initializer is an empty set of parentheses, i.e., () or braces {}

To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
  • if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then every non-static data member and base-class component of T is value-initialized; then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
  • if T is an array type, then each element is value-initialized;
  • otherwise, the object is zero-initialized.

So to summarize

Note The relevant quotation from the standard is highlighted in bold

  • new A : default-initializes (leaves A::m uninitialized)
  • new A() : Zero-initialize A, as the value initialized candidate does not have a user-provided or deleted default constructor. if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
  • new B : default-initializes (leaves B::m uninitialized)
  • new B() : value-initializes B which zero-initializes all fields; if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called
  • new C : default-initializes C, which calls the default ctor. if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called, Moreover If the new-initializer is omitted, the object is default-initialized
  • new C() : value-initializes C, which calls the default ctor. if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called. Moreover, An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized

참고URL : https://stackoverflow.com/questions/29765961/default-value-and-zero-initialization-mess

반응형