자원 - 사용을 마치고 난 후에 시스템에 돌려주어야 하는 모든 것

돌려주지 않는 순간부터 문제가 생긴다.

가장 기본적인 자원은 동적 할당한 메모리를 들 수 있는데, 메모리는 관리해야 하는 많고 많은 자원 중 한 가지

자원에는 파일 서술자도 있고 뮤텍스 잠금도 있으며, 그래픽 유저 인터페이스에서 쓰이는 폰트와 브러시도 자원

수작업으로 해제하는 것이란 어떤 상황에서도 그리 녹녹치 않은 일

예외 발생도 고려해야 하고, return 문이 여러 개 들어 있는 함수도 만들어야 합니다.

 

자원 관리에는 객체가 멈춰야 한다.

함수를 통해 얻어낸 객체를 사용할 일이 없을 때 그 객체를 삭제해야 하는 쪽은 함수의 호출자

투자 객체의 삭제에 실패할 수 있는 경우가 있다. 첫 번째는 함수 어딘가에서 return 문이 들어 있을 가능성

return문이 실행되면 프로그램의 제어가 delete 문까지 도달하지 않게 된다.

혹은 continue나 goto문 처럼 실행해야 하는 곳을 빠져나왔을 때

어떤 문장에서 예외를 던질 수 있다는 점

예외가 던저지면 delete 문이 실행되지 않을 수도 있다.

이렇게 되면 담고 있는 메모리가 누출, 그와 동시에 그 객체가 갖고 있던 자원까지 모두 누출된다.

물른, 하나하나 따져 가면서 꼼꼼하게 프로그램을 만들면 이런 종류의 에러는 막을 수 있지만,

오랜 시간 동안 코드를 변경한다면 어떻게 할지 생각해 봐야 한다.

자원을 객체에 넣고 그 자원 해제를 소멸자가 맡도록 하며, 그 소멸자는 실행 제어가 함수를 떠날 때 호출되도록 만드는 것, 자원을 객체에 넣음으로써, C++가 자동으로 호출해 주는 소멸자에 의해 해당 자원을 저절로 해제할 수 있다.

 

상당수의 자원이 힙에서 동적으로 할당되고, 하나의 블록 혹은 함수 안에서만 씅이는 경우가 잦기 때문에 그 블록 혹은 함수로부터 실행 제어가 빠져나올 때 자원이 해제되는 게 맞다. 표준 라이브러리를 보면 auto_ptr이란 것이 있는데, 이런 용도에 쓰라고 마련된 클래스, auto_ptr은 포인터와 비슷하게 동작하는 객체[스마트 포인터]로서, 가리키고 있는 대상에 대해 소멸자가 자동으로 delete를 불러주도록 설계

 

자원 관리에 객체를 사용하는 방법의 중요한 두 가지 특징

- 자원을 획득한 후에 자원 관리 객체에게 넘긴다.

자원 관리에 객체를 사용하는 아이디어에 대한 업계 용어도 자주 통용되고 있는데, 자원 획즉 즉 초기화라는 이름,

이런 이름이 나온 이유는 자원 획득과 자원 관리 객체의 초기화가 바로 한 문장에서 이루어지는 것이 너무나도 일상적이기 때문, 획득된 자원으로 자원 관리 객체를 초기화하지 않고 그 자원을 그 객체에 대입하는 경우도 종종 있기는 하지만, 어찌 됐든 "자원을 획득하고 나서 바로 자원 관리 객체에 넘겨 준다"는 점은 같다.

- 자원 관리 객체는 자신의 소멸자를 사용해서 자원이 확실히 해제되도록 하자.

소멸자는 어떤 객체가 소멸될 때(유효범위를 벗어나는 경우가 한 가지 예) 자동적으로 호출되기 때문에, 실행 제어가 어떤 경위로 블록을 떠나는가에 상관없이 자원 해제가 제대로 이루어지게 되는 것

객체를 해제하다가 예외가 발생될 수 있는 상황에 빠지면 사태가 많이 꼬이기도 한다.

 

(auto_ptr은 C++ 11이후에 삭제)

auto_ptr은 자신이 소멸될 때 자신이 가리키고 있는 대상에 대해 자동으로 delete를 먹이기 때문에, 어떤 객체를 가리키는 auto-ptr의 개수가 둘 이상이면 절대로 안 된다, 만에 하나 이러한 사태가 되면 자원이 두 번 삭제되는 결과를 낳게 되고, 프로그램은 미정의 동작이 발동 될 것이다. 그래서 auto_ptr은 상당히 유별난 특성을 지니고 있는데, auto_ptr 객체를 복사하면(복사 생성자 혹은 복사 대입 연산자를 통해) 원본 객체는 null로 만든다. 복사하는 객체만이 그 자원의 유일한 소유권을 갖는다고 가정

auto_ptr이 관리하는 객체는 두 개 이상의 auto_ptr 객체가 물고 있으면 안 된다는 요구사항까지 깔려 있는 통에, 동적으로 할당되는 모든 자원에 대한 관리 객체로서 auto_ptr을 쓰는 것은 최선이 아닐 것이다.

예를 들어, STL 컨테이너의 경우엔 원소들이 '정상적인' 복사 동작을 가져야 하기 때문에, auto_ptr은 이들의 원소로 허용되지 않는다.

 

auto_ptr을 쓸 수 없는 상황이라면 그 대안으로 참조 카운팅 방식 스마트 포인터가 괜찮다.

PCSP는 특정한 어떤 자원을 가리키는 외부 객체의 개수를 유지하고 있다가 그 개수가 0이 되면 해당 자원을 자동으로 삭제하는 스마트 포인터

이것만 보면, RCSP의 동작은 가비지 컬렉션과 흡사하다.

참조 상태가 고리를 이루는 경우 (다른 두 객체가 서로를 가리키고 있다든지)를 없앨 수 없다는 점은 가비지 컬렉션과 다르다. TR1에서 제공되는 tr1::shared_ptr이 대표적인 RCSP, 이것을 쓰면 shared_ptr의 복사가 훨씬 자연스러워진다.

복사 동작이 예상대로 이루어지기 때문에, tr1::shared_ptr은 괴상한 복사 동작으로 인해 auto_ptr을 쓸 수 없는 STL 컨테이너 등의 환경에 딱 맞게 쓸 수 있다.

auto_ptr 및 tr1::shared_ptr은 소멸자 내부에서 delete 연산자를 사용, delete[] 연산자가 아니다.

말하자면, 동적으로 할당한 배열에 대해 auto_ptr이나 tr1::shared_ptr을 사용하면 문제가 된다. 심지어 컴파일 에러도 발생하지 않는다.

C++ 표준 라이브러리에서는 동적 할당된 배열을 위해 준비된 auto_ptr 혹은 tr1::shared_ptr 같은 클래스가 제공되지 않는다. 심지어 TR1에서도, 왜냐하면 동적으로 할당된 배열은 이제 vector 혹은 string으로 거의 대체할 수 있기 때문,

배열에 쓸 수 없는 auto_ptr이라든지 tr1::shared_ptr을 원한다면 부스트에 있다.

(boost::scoped_array, boost::shared_array)

자원 해제를 일일이 하다 보면 언젠가 잘못을 저지르고 만다. 이미 널리 쓰이고 있는 자원 관리 클래스를 활용하는 것도 조언을 쉽게 지킬 수 있다. 자원 관리 클래스를 직접 만드는 것도 좋다.

함수의 반환 타입이 포인터일 경우 이 부분 떄문에 문제가 생길 수 있다. 

반환된 포인터에 대한 delete 호출을 호출자 쪽에서 해야 하는데, 그것을 잊어버리고 넘어가기 쉽기 떄문

 

* 자원 누출을 막기 위해, 생성자 안에서 자원을 획득하고 소멸자에서 그것을 해제하자

'C++ > Effective' 카테고리의 다른 글

생성자, 소멸자, 대입 연산자(3)  (0) 2022.02.16
생성자, 소멸자, 대입 연산자(2)  (0) 2022.02.10
생성자, 소멸자, 대입 연산자(1)  (0) 2022.02.04
객체 초기화  (0) 2022.01.31
const  (0) 2022.01.25

정의

정의란 개념은 일반적으로 어떤 대상을 명확하게 규정하는 것

C++에서 말하는 정의를 이해하기 위해서는 조금은 구체적인 의미를 알고 있어야만 한다.

C++에서 말하는 정의란 바로 객체를 실제로 만들겠다는 것을 의미

객체를 만들겠다는 것은 메모리를 할당하겠다는 것

해당 객체를 위한 메모리 영역을 확보하는 것이 정의

프로그램 시작 시에 전역 객체는 데이터 영역의 메모리 공간을 차지하게 된다.

지역 객체란 함수 인자를 포함하여 함수 안에서 정의된 객체를 만한다.

지역 객체는 스택의 메모리 공간을 차지한다.

간단하게 함수의 본체가 있을 경우 함수가 정의되었다.

컴파일러는 함수 본체를 어셈블리로 변경하고, 변경된 어셈블리는 코드 영역에 저장

함수도 일반 객체처럼 메모리의 공간을 차지하게 된다.

정의란 어떤 대상이 실제로 존재할 수 있도록 자리(메모리 영역)를 만들어주는 작업

정의가 이것만 있는 것은 아니다.

클래스의 경우 정의 개념이 조금 달라진다.

클래스 정의란 실제로 이 클래스가 어떻게 구성되어 있는지를 나타내는 설계도

해당 설계도 또한 메모리에는 저장되어야 할 것

메모리 영역을 차지한다는 점에서 기존의 정의에 부합될 수 있다.

그러나 기존 변수들과의 정의와는 큰 차이가 있는데, 메모리 영역의 성격이 전혀 다르다

기존 변수들이 차지하는 메모리 영역은 프로세스가 사용하는 가상 메모리를 나타내지만,

클래스의 설계도가 저장되는 메모리 영역은 프로세스와는 상관없는 컴파일러가 사용하는 메모리

즉, 클래스 설계가 저장되는 메모리는 실제 프로그램이 사용하는 메모리와는 전혀 관련이 없다.

클래스 정의에는 클래스의 멤버 객체가 선언되거나 멤버 함수가 선언 및 정의될 수 있다.

클래스 멤버 객체가 선언된다는 의미는 클래스 객체가 생성되어 객체에 대한 메모리가 할당될 경우 할당된 영역의 특정 부분이 멤버 객체에게 할당된다는 것을 나타낸다.

멤버 함수의 경우 선언될 경우 해당 함수가 멤버 함수임을 알리게 되고, 정의될 때는 프로세스가 시작될 경우 함수의 본체가 코드 영역의 메모리를 차지하게 됨

 

간단히 정의에 대해서 정리를 한다면 어떤 대상이 존재할 수 있도록 메모리를 할당하는 과정이 바로 정의이며 일반적인 객체와 함수들의 경우 정의에 의해서 할당되는 메모리는 가상 메모리이지만, 클래스의 경우는 정의에 의해서 할당되는 메모리는 컴파일러가 사용하는 메모리

 

선언

어떤 객체를 사용하기 위해서 정의를 하였을 때, 특정 메모리 영역을 차지하는 객체가 생성된 것

생성된 객체의 존재를 모를 경우 객체에 접근할 수조차 없을 것이다.

선언이란 어떤 객체가 존재하고 있음을 알리는 역할

클래스를 선언한다는 것은 이런 클래스가 존재하고 있으니 타입으로 사용해도 된다는 것을 나타낸다.

따라서 선언 이후부터 해당 객체에 대해서 읽고 쓰는 것을 할 수 있다.

 

정의는 곧 선언을 포함한다.

어떤 객체를 정의하는 순간 해당 객체는 알려지므로 선언을 따로 해줄 필요가 없다.

그렇다면 선언이 필요없을 것이 아닐까 생각하지만 선언이 꼭 필요한 경우가 있다.

전역 변수와 전역 함수를 정의할 때, 특정한 cpp에서 정의를 했을 때 다른 cpp에서 전역 변수와 전역 함수를 사용하려 하면 컴파일 에러가 발생한다. 무엇인지 전혀 알 수 없기 때문이다.

정의되었을 때 선언도 동시에 되는데, 문제는 선언이 적용되는 범위가 오직 특정한 cpp에만 해당되기 때문이다.

이럴 때 바로 선언만 해주는 것이 필요하다.

 

exturn이라는 키워드를 사용한다면 순수하게 함수 형식만 나와있고, 본체는 존재하지 않고 선언만 하도록 할 수 있다.

그렇다면 다른 cpp에서 정의해주면 문제가 해결될 수 있을까라고 생각하는데 이럴 경우에는 중복 정의 문제가 발생한다, 링크 단계에서 에러 처리를 하게 된다.

중복 정의를 허용하지 않는 이유는 서로 다른 cpp 파일에 으름은 같지만 타입이 다른 객체가 정의될 경우 어떤 것을 선택해야만 할지 알 수 없기 때문이다, 함수도 마찬가지이다. 이름도 같고 반환 타입, 인자 타입까지 일치하지만 본체가 다른 함수가 중복으로 정의될 경우 어떤 함수가 선택되어야 할지 혼란이 된다.

 

어떤 소스 파일에서 정의를 할 경우 해당 소스 파일에 대해서는 선언까지 자동으로 이루어진다.

그러나 다른 소스파일에서 이미 정의된 객체를 사용하고자 할 경우에는 순수하게 선언만 해주어야만 한다.

만일 정의를 중복으로 하게 될 경우 링크 에러가 발생하게 된다.

'C++ > Fundamental' 카테고리의 다른 글

auto  (0) 2022.02.13
typedef  (0) 2022.02.07
참조 타입  (0) 2022.02.07
날짜 시간  (0) 2022.02.02
문자열  (0) 2022.01.28

대입 연산자는 *this의 참조자를 반환하게 하자

 

대입 연산은 여러 개가 사슬처럼 엮일 수 있는 성질을 갖고 있다.

x = y = z = 15;

 

대입 연산이 가진 또 하나의 특성은 바로 우측 연관 연산이라는 점

x = ( y = ( z = 15)));

 

15가 z에 대입되고, 그 대입 연산의 결과가 y에 대입된 후에, y에 대한 대입 연산의 결과가 x에 대입되는 것

이렇게 대입 연산이 사슬처럼 엮이려면 대입 연산자가 좌변 인자에 대한 참조자를 반환하도록 구현되어 있을 것

만드는 클래스에 대입 연산자가 혹시 들어간다면 이 관례를 지키는 것이 좋다.

"좌변 객체의 참조자를 반환하게 만들자"라는 규약은 단순 대입형 연산자 말고도 모든 형태의 대입 연산자에서 지켜져야 한다. 따르지 않고 코드를 작성하더라도 컴파일이 안 된다거나 하는 것은 아니다. 하지만 이 관례는 모든 기본 제공 타입들이 따르고 있을 뿐만 아니라 표준 라이브러리에 속한 모든 타입에서도 따르고 있다는 점은 무시 못할 것

 

operator=에서는 자기 대입에 대한 처리가 빠지지 않도록 하자

 

자기 대입이란, 어떤 객체가 자기 자신에 대해 대입 연산자를 적용하는 것을 말함

가리키는 대상이 같으면 자기 대입이 된다. 언뜻 보기에 명확하지 않은 이러한 자기 대입이 생기는 이유는 여러 곳에서 하나의 객체를 참조하는 상태, 다시 말해 중복 참조라고 불리는 것 때문이다. 같은 타입으로 만들어진 객체 여러 개를 참조자 혹은 포인터로 물어 놓고 동작하는 코드를 작성할 때는 같은 객체가 사용될 가능성을 고려하는 것이 일반적

같은 클래스 계통에서 만들어진 객체라 해도 굳이 똑같은 타입으로 선언할 필요는 없다.

파생 클래스 타입의 객체를 참조하거나 가리키는 용도로 기본 클래스의 참조자나 포인터를 사용해도 된다.

자원 관리 용도로 항상 객체를 만들어야 할 것, 이렇게 만든 자원 관리 객체들이 복사될 때 나름대로 잘 동작하도록 코딩

이때 조심해야 하는 것이 대입 연산자, 신경 쓰지 않아도 자기 대입에 대해 안전하게 동작해야 한다.

자원 관리를 하기엔 어려운 일, 어쩌면 자원을 사용하기 전에 해제할 수도 있다.

자기 참조 문제는 operator= 내부에서 *this(대입되는 대상)와 새롭게 만들 객체가 같은 객체일 수도 있기에 좋지 않다.

둘이 같은 객체일 경우 delete 연산자가 *this 객체의 비트맵에만 적용되는 것이 아니라 새로운 객체까지 적용되어 버린다. 이 함수가 끝나는 시점이 되면 해당 객체는 자신의 포인터 멤버를 통해 물고 있던 객체가 어처구니없게도 삭제된 상태가 되는 불상사를 당하게 된다.

이런 에러에 대한 대책은 operator=의 첫머리에서 일치성 검사를 통해 자기 대입을 점검하는 것

이전 버전의 operator=이 자기 대입에 안전하지 못할 뿐만 아니라 예외에도 안전하지 않다.

예외 안전성에 대해서는 이번 것도 여전히 문젯거리를 안고 있다.

특히 신경 쓰이는 부분이 'new Bitmap' 표현식, 이 부분에서 예외가 터지게 되면( 동적 할당에 필요한 메모리가 부족하다든지 Bitmap 클래스 복사 생성자에서 예외를 던진다든지 해서), 객체는 결국 삭제된 Bitmap을 가리키는 포인터만 가지게 됩니다. 이런 포인터는 delete 연산자를 안전하게 적용할 수도 없고, 안전하게 읽는 것조차 불가능

operator=을 예외에 안전하게 구현하면 대개 자기 대입에도 안전한 코드가 나오게 되어 있습니다.

원본 비트맵을 복사해 놓고, 복사해 놓은 사본을 포인터가 가리키게 만든 후, 원본을 삭제하는 순서로 실행하면 된다.

이 방법이 자기 대입을 처리하는 가장 효율적인 방법이라고는 할 수 없겠지만, 동작에는 아무 문제가 없다.

효율이 너무나 신경 쓰인 나머지, 일치성 테스트를 함수 앞단에 도로 붙여 놓고 싶을 수도 있다.

하지만 자기 대입은 자주 일어나지 않는다. 일치성 검사 코드가 들어가면 그만큼 코드가 커지는 데다가, 처리 흐름에 분기를 만들게 되므로 실행 시간 속력이 줄어들 수 있다.

예외 안전성과 자기 대입 안전성을 동시에 가진 operator=을 구현하는 방법으로, 문장의 실행 순서를 수작업으로 저장하는 것 외에 다른 방법이 하나 더 있다.

 

* operator=을 구현할 때, 어떤 객체가 그 자신에 대입되는 경우를 제대로 처리하도록 만들자.

원본 객체와 복사 대상 객체의 주소를 비교해도 되고, 문장의 순서를 적절히 조정할 수도 있으며, 복사 후 맞바꾸기 기법을 써도 된다.

* 두 개 이상의 객체에 대해 동작하는 함수가 있다면, 이 함수에 넘겨지는 객체들이 사실 같은 객체인 경우에 정확하게 동작하는지 확인

 

객체의 모든 부분을 빠짐없이 복사

 

객체의 안쪽 부분을 캡슐화한 객체 지향 시스템 중 설계가 잘 된 것들을 보면, 객체를 복사하는 함수가 두 개만 있다.

복사 생성자와 복사 대입 연산자, 이 둘을 통틀어 객체 복사 함수라고 부른다

객체 복사 함수는 컴파일러가 필요에 따라 만들어내기도 한다.

컴파일러가 생성한 복사 함수는 저절로 만들어졌지만 동작은 기본적인 요구에 아주 충실하다. 복사되는 객체가 갖고 있는 데이터를 빠짐없이 복사한다.

객체 복사 함수를 선언한다는 것은 컴파일러가 만든 기본 동작이 별로라는 것

부분 복사 이어도 컴파일러는 그냥 실행한다.

클래스에 데이터 멤버를 추가했으면, 추가한 데이터 멤버를 처리하도록 복사 함수를 다시 작성할 수밖에 없다.

클래스 상속으로 인해서 파생된 클래스가 상속한 데이터의 멤버들의 사본도 클래스에 들어 있을 때, 복사를 하고 있지 않는다면 기본 생성자에 의해 초기화된다. 복사가 아니라 기본적인 초기화가 된다.

복사 대입 연산자가 기본 클래스의 데이터 멤버를 건드릴 시도도 하지 않고 때문에, 기본 클래스의 데이터 멤버는 변경되지 않고 그대로 있게 된다.

파생 클래스에 대한 복사 함수를 스스로 만든다고 결심했다면 기본 클래스 부분을 복사에서 빠뜨리지 않도록 주의

기본 클래스 부분은 private 멤버일 가능성이 높기 때문에, 직접 건드리긴 어렵다.

파생 클래스의 복사 함수 안에서 기본 클래스의 복사 함수를 호출해야 한다.

즉, 해당 클래스의 데이터 멤버를 모두 복사, 클래스가 상속한 기본 클래스의 복사 함수도 호출해야 한다.

양대 복사 함수(복사 생성자와 복사 대입 연산자)는 비슷하기 때문에 한쪽에서 다른 쪽을 호출하면 된다고 생각하겠지만 절대 불가능하다.

복사 대입 연산자에서 복사 생성자를 호출하는 것부터 말이 안 된다. 객체를 '생성'하는 것이기 때문이다.

특정한 조건에서 객체의 데이터가 훼손되어 버릴 수 있어서 매우 위험하다.

복사 생성자에서 복사 대입 연산자를 호출하는 것 또한 말도 안 된다.

생성자의 역할은 새로 만들어진 객체를 초기화하는 것, 대입 연산자의 역할은 이미 초기화가 끝난 객체에게 값을 주는 것, 초기화된 객체에만 적용된다, 하지만 생성 중인 객체에다가 대입이라는 건, 초기화된 객체에 대해서만 의미를 갖는 동작을 아직 초기화도 안 된 객체에 대해 한다는 것

양쪽에서 겹치는 부분을 별도의 멤버 함수에 분리해 놓은 후에 이 함수를 호출하게 만드는 것

대게 이런 용도의 함수는 private 멤버로 두는 경우가 많고, 이름이 init으로 시작하는 경우도 많다.

안전할 뿐만 아니라 검증된 방법이므로, 복사 생성자와 복사 대입 연산자에 나타나는 코드 중복을 제거하는 방법으로 사용하는 것을 사용하는 것이 좋다.

'C++ > Effective' 카테고리의 다른 글

자원 관리(1)  (0) 2022.02.21
생성자, 소멸자, 대입 연산자(2)  (0) 2022.02.10
생성자, 소멸자, 대입 연산자(1)  (0) 2022.02.04
객체 초기화  (0) 2022.01.31
const  (0) 2022.01.25

자동 변수 auto

 

자동 변수는 단순히 지역 변수를 의미, 함수 안에서만 사용될 수 있는 것

auto라는 키워드는 생략해도 무방했다.

전부 생략해서 사용했기에 auto라는 키워드가 오래전부터 존재하였으나 생소한 것이 되어버렸다.

현재 auto는 컴파일 타임에 자동으로 적절한 타입으로 변경되는 키워드

근거는 변수가 초기화될 때 바로 어떤 타입으로 간주할 수 있기 때문이다.

auto는 컴파일 타임에 적절한 타입을 추론해서 해당 타입으로 변경되어야 한다.

현재까지는 auto가 타입을 추론하기 위해서는 선언 즉시 초기화가 이루어져야만 하며, 초기화가 존재하지 않을 경우 타입 추론에 실패하여 컴파일 에러가 발생하다.

 

auto는 초기화를 동반한 선언이 있을 경우 해당 초기화식을 통하여 타입을 추론할 수 있다.

초기 화식에서 함수를 사용하게 되면, 반환 타입에 따라서 변환될 수 있다.

초기화식 없이 선언될 경우 타입을 추론할 수 없다.

따라서 초기화식이 존재하지 않는 경우인 멤버 변수와 함수 인자에는 사용될 수 없다.

auto는 오직 비 참조 타입으로만 추론된다는 것을 기억해야만 한다.

auto를 이용해서 참조 타입을 사용하고 싶다면 auto&와 같은 표기를 사용해야 한다.

auto는 컴파일 타임에 자동으로 타입이 추론되기 때문에 잘만 사용하면 편하다.

특히 타입의 이름이 무척 길 경우 타이핑을 줄여주는 효과를 주기도 한다.

보통 auto는 STL 컨테이너와 함께 자주 쓰이는데,

STL 컨테이너의 반복자 타입의 이름이 생각보다 타이핑 하기에는 조금 길어지기 때문.

auto가 없었더라면 반복자를 정의하기 위해서 반복자 타입인 vector<int>::iterator를 모두 써줘야만 한다.

더 긴 타입의 경우 auto를 사용하지 않을 경우 코드가 어지럽게 보이는 경우도 적지 않다.

사실 typedef를 사용한다면 긴 타입도 짧은 이름으로 새롭게 정의할 수 있기 때문에 꼭 auto만으로 타이밍을 줄일 수 있는 것은 아니다. 그럼에도 auto를 사용하면 typedef를 할 수고조차 덜어주기 때문에 편리하게 사용할 수 있다.

auto는 typedef를 사용하지 못하는 타입에 대해서도 자동으로 추론을 할 수 있는 능력이 있기 때문에 람다 타입을 받는데도 사용될 수 있다.

 

지금까지의 정리

결국 프로그래밍의 목적은 데이터를 처리하는 것이며, 데이터에는 보통 타입이 존재하기 때문,

타입에 대한 정확한 이해는 프로그래밍의 기초를 튼튼하게 만들어 준다.

'C++ > Fundamental' 카테고리의 다른 글

선언과 정의의 구분(1)  (0) 2022.02.19
typedef  (0) 2022.02.07
참조 타입  (0) 2022.02.07
날짜 시간  (0) 2022.02.02
문자열  (0) 2022.01.28

+ Recent posts