Value-initialization
이는 빈 초기화자로 객체가 생성될 때 수행되는 초기화입니다.
목차 |
구문
T
()
|
(1) | ||||||||
new
T
()
|
(2) | ||||||||
Class
::
Class
(
...
)
:
member
()
{
...
}
|
(3) | ||||||||
T
object
{};
|
(4) | (C++11 이후) | |||||||
T
{}
|
(5) | (C++11 이후) | |||||||
new
T
{}
|
(6) | (C++11 이후) | |||||||
Class
::
Class
(
...
)
:
member
{}
{
...
}
|
(7) | (C++11 이후) | |||||||
설명
값 초기화는 다음과 같은 상황에서 수행됩니다:
모든 경우에, 빈 중괄호 쌍
{}
이 사용되고
T
가 aggregate type인 경우,
aggregate initialization
이 value-initialization 대신 수행됩니다.
|
만약
|
(C++11부터) |
값 초기화의 효과는 다음과 같습니다:
-
만약
T가 (cv 한정자가 있을 수 있는) 클래스 타입인 경우:
-
그렇지 않고
T가 배열 타입인 경우, 배열의 각 요소가 값 초기화됩니다. - 그렇지 않은 경우, 객체는 제로 초기화됩니다.
참고 사항
구문
T object
(
)
;
는 객체를 초기화하지 않으며, 인수를 받지 않고
T
를 반환하는 함수를 선언합니다. C++11 이전에 명명된 변수를 값 초기화하는 방법은
T object
=
T
(
)
;
으로, 임시 객체를 값 초기화한 후 해당 객체를 복사 초기화하는 방식입니다: 대부분의 컴파일러는 이 경우
복사를 최적화하여 제거합니다
.
참조는 값 초기화될 수 없습니다.
함수 스타일 캐스트
에서 설명된 바와 같이,
T
(
)
(1)
구문은
T
가 배열 타입을 명시하는 경우 금지되지만,
T
{
}
(5)
구문은 허용됩니다.
모든 표준 컨테이너(
std::vector
,
std::list
등)는 단일
size_type
인수로 생성될 때 또는
resize
(
)
호출로 크기가 증가할 때 해당 요소들을 값 초기화합니다. 단, 해당 할당자가
construct
의 동작을 사용자 정의하는 경우는 예외입니다.
예제
#include <cassert> #include <iostream> #include <string> #include <vector> struct T1 { int mem1; std::string mem2; virtual void foo() {} // T1이 aggregate가 아님을 보장 }; // 암시적 기본 생성자 struct T2 { int mem1; std::string mem2; T2(const T2&) {} // 사용자 제공 복사 생성자 }; // 기본 생성자 없음 struct T3 { int mem1; std::string mem2; T3() {} // 사용자 제공 기본 생성자 }; std::string s{}; // 클래스 => 기본 초기화, 값은 "" int main() { int n{}; // 스칼라 => 제로 초기화, 값은 0 assert(n == 0); double f = double(); // 스칼라 => 제로 초기화, 값은 0.0 assert(f == 0.0); int* a = new int[10](); // 배열 => 각 요소의 값 초기화 assert(a[9] == 0); // 각 요소의 값은 0 T1 t1{}; // 암시적 기본 생성자를 가진 클래스 => assert(t1.mem1 == 0); // t1.mem1은 제로 초기화, 값은 0 assert(t1.mem2 == ""); // t1.mem2는 기본 초기화, 값은 "" // T2 t2{}; // 오류: 기본 생성자가 없는 클래스 T3 t3{}; // 사용자 제공 기본 생성자를 가진 클래스 => std::cout << t3.mem1; // t3.mem1은 기본 초기화되어 불확정 값 assert(t3.mem2 == ""); // t3.mem2는 기본 초기화, 값은 "" std::vector<int> v(3); // 각 요소의 값 초기화 assert(v[2] == 0); // 각 요소의 값은 0 std::cout << '\n'; delete[] a; }
가능한 출력:
42
결함 보고서
다음 동작 변경 결함 보고서는 이전에 게시된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 178 | C++98 |
value-initialization이 없었음; 빈 초기화자는 default-
initialization을 수행했음 (비록 new T ( ) 는 zero-initialization도 수행했지만) |
빈 초기화자는
value-initialization을 수행함 |
| CWG 543 | C++98 |
사용자 제공 생성자가 없는 클래스 객체에 대한 value-
initialization은 각 하위 객체를 value-initialization하는 것과 동등했음 (이는 사용자 제공 default constructor가 있는 멤버를 zero-initialize하지 않을 수 있음) |
전체 객체를
zero-initialize한 후, default constructor를 호출함 |
| CWG 1301 | C++11 |
삭제된 default constructor를 가진 union의 value-
initialization이 zero-initialization으로 이어짐 |
해당 union은
default-initialized됨 |
| CWG 1368 | C++98 |
어떤 사용자 제공 생성자라도 zero-initialization이
생략되도록 했음 |
사용자 제공 default constructor만이
zero-initialization을 생략함 |
| CWG 1502 | C++11 |
사용자 제공 default constructor가 없는 union을 value-
initializing할 때 default member initializer가 있음에도 객체만 zero-initialized됨 |
zero-initialization 후
default-initialization을 수행함 |
| CWG 1507 | C++98 |
사용자 제공 생성자가 없는 클래스 객체에 대한 value-
initialization은 default constructor가 trivial할 때 후자의 유효성을 검사하지 않았음 |
trivial default constructor의
유효성이 검사됨 |
| CWG 2820 | C++98 |
zero-initialization 이후의 default-initialization에
non-trivial constructor가 필요했음 |
필요하지 않음 |
| CWG 2859 | C++98 |
클래스 객체에 대한 value-initialization은 default-
initialization이 실제로 사용자 제공 constructor를 선택하지 않는 경우에도 zero-initialization을 수반할 수 있었음 |
이 경우
zero-initialization이 발생하지 않음 |