6. 타입과 선언
6-3 선언
C++ 에서 어떠한 식별자를 사용하기 위해서는, 그 전에 반드시 선언 되어야 한다. -> 해당 이름이 어떤 종류의 개체를 가리키는지 컴파일러에게 알려주기 위해 타입이 지정되어야 한다.
6.3.5 초기화
초기화를 하는 방법은 다음과 같다.
X a1 {v}; // C++11 에서 처음 등장! (사용하기를 권장)X a2 = {v}; // 배열 초기화X a3 = v; // 대입 초기화X a4 (v); // 생성자 초기화
하지만 X a1 {v}; 해당 방식이 다음과 같은 이점을 가지고 있기 때문에, 1순위로 사용하기를 권장한다. -> 하지만 auto 타입을 사용할 때, 타입지정의 혼란을 줄 수 있기 때문에, = 를 사용하자. (일반 타입인지, 배열인지 판단의 혼란을 줄 수 있다..)
일관성: 중괄호를 사용하여 초기화하는 것은 다른 유형의 초기화와 일관성을 유지합니다. 예를 들어, 배열 초기화나 객체 초기화에도 중괄호를 사용하는 것이 권장됩니다.
축소 변환 방지: 중괄호 초기화는 형 변환 문제를 방지합니다. 예를 들어,
int i {3.14};와 같이 실수를 정수로 변환하려고 하면 컴파일러는 경고를 발생시킵니다. 하지만int i = 3.14;와 같이 할당 연산자를 사용할 경우 이러한 경고가 발생하지 않을 수 있습니다.초기화 되지 않은 변수 방지 : 중괄호 초기화는 모든 변수가 초기화 되도록 보장해, 초기화되지 않은 변수로 인한 문제를 예방합니다. -> 해당 타입의 기본값으로 초기화 한다.
int x{}; // 0으로 초기화 int* ptr{}; // nullptr로 초기화
6.3.5.1 초기화가 없는 경우
자동적으로 초기화되는 경우
전역변수, 정적변수 : 전역변수와 정적변수는 프로그램이 실행될 때, 자동적으로 초기화된다.
클래스 멤버변수 : 클래스 멤버 변수는 클래스 개체 생성시 자동적으로 초기화된다.
동적 할당 : 기본적으로 동적 할당 시 초기화되지 않는다. 하지만, 중괄호
{}를 사용한다면, 자동적으로 초기화 된다.int* ptr = new int; // 초기화되지 않은 상태 int* ptrInit = new int{}; // 0으로 초기화
6.3.6 타입의 추론 auto 와 decltype()
auto 와 decltype 은 타입을 추론하기 위한 매커니즘이다.
여기서 수행되는 추론은 컴파일러가 이미 알고 있는 표현식의 타입을 알려주기만 할 뿐이다.
6.3.6.1 auto 타입 지정자
auto 타입 지정자를 사용해 초기화를 하게되면, 값을 통해서 타입을 컴파일러가 추론하게 된다.
123 처럼 간단한 값에 auto 를 사용하는 것은 가독성을 해칠 뿐, 큰 도움이 되지 않는다.
타입이 쓰기 어렵고 파악하기 어려울수록 auto 가 좀 더 빛을 바란다. -> STL 컨테이너에 iterator 와 같이 긴 타입을 사용할 때 빛을 바란다.
6.3.6.2 auto 와 {} 리스트
{} 를 사용한 변수 초기화는 6.3.5 초기화 의 장점이 있기에 타입이 정해져 있는 상황에서는 유효하게 적용된다.
하지만, auto 의 경우에는 의도한대로 사용되지 않기 때문에 auto 를 초기화 시 = 를 사용해야 한다!
아래의 경우 아예 의미가 달라진다!
int i1 {12345} // i1 은 12345auto i1 {12345} // i1 은 int 리스트
6.3.6.3 decltype() 지정자
적합한 초기화 식이 있다면 auto 를 사용할 수 있다.
하지만 경우에 따라 초기화 할 변수를 정의하지 않고 타입이 추론되기를 원할 수도 있다. -> 이러한 경우 decltype(expr) 을 사용할 수 있다.
변수나 함수의 반환값을 통해 타입을 추론합니다. -> 즉, 주어진 변수나 함수의 반환값의 타입을 그대로 가져와서 사용합니다.
특히 decltype 은 템플릿과 함께 사용될 때 정말 유용하다. -> 템플릿 함수의 경우, 반환타입이 매개변수에 의존적인 경우가 있는데, 후행 반환 타입을 decltype 과 함께 사용하면, 매개변수의 타입을 지정하고, 반환 타입을 지정할 수 있다. -> 후행 반환 타입을 통해서 컴파일 타임에 리턴 타입을 체크할 수 있다.
또한 decltype 은 반환 타입이 긴 경우 매우 auto 와 함께 사용하면 가독성이 좋은 코드를 만들 수 있다.
decltype과auto의 차이점
auto는 변수의 초기화 값에 기반하여 타입을 추론합니다.
decltype은 주어진 표현식이나 변수의 타입을 추론합니다.예제
6.4 Object와 값
C++ 에서 Object란 '메모리에 할당된 데이터' 를 의미한다.
6.4.1 lvalue, rvalue
C++ 에서 lvalue, rvalue 라는 개념이 존재하는데,
lvalue 는 Object를 참조하는 표현식을 의미한다. -> 주소가 있다는 것을 의미한다!
lvalue 를 보완하기 위한 rvalue 의 개념은 아래와 같다.
lvalue 가 아닌값?
임시적인 값 (함수에 의해 반환되는 값 등..)
6.4.2 Object의 수명
Object의 수명은 생성자가 끝날 때 시작되고, 소멸자가 실행하면 종료된다. -> 기본형 타입은 아무 일도 하지 않는 기본 생성자와 소멸자를 가진 것으로 간주될 수 있다.
Object의 수명에 따라 다음과 같이 구분할 수 있다.
Automatic Object : 중괄호({}) 안에 존재하는 변수는 그 범위를 벗어나면, 수명이 끝이난다. -> 이러한 Object 는 스택에 할당된다.
정적(static) Object : 전역이나, 네임스페이스 유효 범위에서 선언된 Object, 함수 안에서 선언된 static, 클래스 정보 등은 단 한번 생성되고 초기화되며 프로그램 종료될 때까지 생존한다.
동적 Object : new 와 delete 연산자를 통해 수명을 직접적으로 제어할 수 있는 Object -> 이러한 Object 는 힙에 할당된다.
Temporary Object(rvalue 대부분이 해당)
Thread-Local Object : 스레드의 라이프사이클과 동일
6.5 타입 별칭
다음과 같은 방법을 사용해 타입의 별칭을 지어줄 수 있다.
using
typedef
using 과 typedef 의 차이
typedef 는 C 언어부터 존재한 구문으로, 기본적인 타입 별칭을 만드는데 사용된다.
using 은 C++11 부터 도입된 구문으로, 더 복잡한 타입 정의와 템플릿과의 통합에서 더 유연하고 강력하다.
typedef 에 비해 using 이 가독성이나 표현의 범위가 더 넓다. -> C++11 이후에 코드에서는 대부분 using 을 사용하는 것이 권장된다.
Last updated