기본값, 값 및 제로 초기화 혼란
값 및 기본값 및 제로 초기화에 대해 매우 혼란 스럽습니다. 특히 다른 표준 C ++ 03 및 C ++ 11 (및 C ++ 14 ) 을 위해 시작될 때 .
나는 누군가가 도움을 줄 수 있다면 많은 사용자에게 도움이 될 것이므로 더 일반적으로 만들기 위해 Value- / Default- / Zero- Init C ++ 98 및 C ++ 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
-불확실한 값 (A
POD 임)new A()
-제로 초기화new B
-기본 구성 (B::m
초기화되지 않음,B
POD가 아님)new B()
-기본 구성 (B::m
초기화되지 않음)new C
-기본 구성 (C::m
0으로 초기화 됨,C
POD가 아님)new C()
-기본 구성 (C::m
0으로 초기화 됨)new D
-기본 구성 (D::m
초기화되지 않음,D
POD가 아님)new D()
- 기본 구성? (D::m
초기화되지 않음)
C ++ 03 준수 컴파일러에서는 다음과 같이 작동해야합니다.
new A
-불확실한 값 (A
POD 임)new A()
-value-initializeA
, POD이므로 0으로 초기화됩니다.new B
B::m
-default -initializes ( 초기화되지B
않은 상태로두고 POD가 아님)new B()
- 값 초기화합니다B
사용자 정의 반대로 기본 ctor에 이후의 모든 필드를 제로 - 초기화 컴파일러가 생성됩니다.new C
C
-default -initializes , 기본 ctor를 호출합니다. (C::m
0으로 초기화 됨,C
POD가 아님)new C()
C
-value -initializes , 기본 ctor를 호출합니다. (C::m
0으로 초기화 됨)new D
-기본 구성 (D::m
초기화되지 않음,D
POD가 아님)new D()
- 가치 초기화 D? , 기본 ctor (D::m
초기화되지 않음) 를 호출합니다.
기울임 꼴 값 및? 불확실성이 있습니다.이 문제를 해결하는 데 도움을주세요 :-)
C ++ 11 준수 컴파일러에서는 다음과 같이 작동해야합니다.
??? (여기서 시작하면 어쨌든 잘못 될 것입니다)
C ++ 14 준수 컴파일러에서는 다음과 같이 작동해야합니다. ??? (여기서 시작하면 어쨌든 잘못 될 것입니다.) (답변에 따른 초안)
new A
-기본 초기화A
, 컴파일러 생성. ctor, (A::m
초기화되지 않은 상태) (A
POD 임)new A()
-값 초기화A
, [dcl.init] / 8의 2. 지점 이후 제로 초기화new B
-기본 초기화B
, 컴파일러 생성. ctor, (B::m
초기화되지 않은 리프 ) (B
은 POD가 아님)new B()
- 값 초기화합니다B
사용자 정의 반대로 기본 ctor에 이후의 모든 필드를 제로 - 초기화 컴파일러가 생성됩니다.new C
C
-default -initializes , 기본 ctor를 호출합니다. (C::m
0으로 초기화 됨,C
POD가 아님)new C()
C
-value -initializes , 기본 ctor를 호출합니다. (C::m
0으로 초기화 됨)new D
-기본 초기화D
(D::m
초기화되지 않음,D
POD가 아님)new D()
-D
기본 ctor를 호출하는 value-initializes (D::m
초기화되지 않음)new E
-compE
를 호출하는 default-initializes . gen. ctor. (E::m
초기화되지 않음, E는 POD가 아님)new E()
-값-초기화E
, [dcl.init] / 8의E
2 점 이후 0으로 초기화 됨 )new F
-compF
를 호출하는 default-initializes . gen. ctor. (F::m
초기화되지 않음,F
POD가 아님)new F()
-value -initializesF
, 1부터 기본값으로 초기화F
됩니다. [dcl.init] / 8에서 지정합니다 (F
ctor 함수는 사용자가 선언하고 첫 번째 선언에서 명시 적으로 기본값이 설정되거나 삭제되지 않은 경우 사용자가 제공합니다. 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-initializem
. And this should be equivalent forA
andB
.- if
new C
andnew 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, nowm
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 forT
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, ifT
’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
- In C++1998 there are 2 types of initialization: zero and default
- 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:
 assignment-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.
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-PODclass 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_
- 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
'your programing' 카테고리의 다른 글
이 앱에는 구성된 Android 키 해시가 없습니다. (0) | 2020.10.08 |
---|---|
ListView에 항목을 빠르게 추가하는 방법은 무엇입니까? (0) | 2020.10.08 |
TensorFlow에서 CSV 데이터를 * 실제로 * 읽는 방법은 무엇입니까? (0) | 2020.10.08 |
Blob URL을 일반 URL로 변환 (0) | 2020.10.07 |
대기 후 HttpContext.Current가 null 인 이유는 무엇입니까? (0) | 2020.10.07 |