KoreanFoodie's Study
Effective Modern C++ | 항목 5 : 명시적 형식 선언보다는 auto 를 선호하라 본문
Tutorials/C++ : Advanced
Effective Modern C++ | 항목 5 : 명시적 형식 선언보다는 auto 를 선호하라
GoldGiver 2022. 10. 26. 09:50
C++ 프로그래머의 필독서이자 바이블인, 스콧 마이어스의 Modern Effective C++ 를 읽고 기억할 내용을 요약하고 있습니다. 꼭 읽어보시길 추천드립니다!
항목 5 : 명시적 형식 선언보다는 auto 를 선호하라
핵심 :
1. auto 변수는 반드시 초기화 해야 하며, 이식성 또는 효율성 문제를 유발할 수 있는 형식 불일치가 발생하는 경우가 거의 없으며, 대체로 변수의 형식을 명시적으로 지정할 때보다 타자량도 더 적다.
2. auto 로 형식을 지정한 변수는 항목 2 와 항목 6 에서 설명한 문제점들을 겪을 수 있다.
아래 예시를 보면, auto 를 쓰는 것이 여러모로 훌륭하다는 것을 한눈에 파악할 수 있을 것이다.
template<typename It>
void print_from_b_to_e(It b, It e)
{
for (; b != e; ++b)
{
typename std::iterator_traits<It>::value_type
currValue = *b;
std::cout << currValue << std::endl;
// auto 를 쓰면 훨씬 간단하다!
auto currValue2 = *b;
std::cout << currValue2 << std::endl;
}
}
또한, auto 는 예전에는 컴파일러만 알던 형식을 지정할 수도 있고, 람다 표현식의 매개변수에도 사용할 수 있다.
std::function<bool(const std::unique_ptr<Widget>& p1,
const std::unique_ptr<Widget>& p2)>
derefUPLess_bad =
[] (const std::unique_ptr<Widget>& p1,
const std::unique_ptr<Widget>& p2)
{ return *p1 < *p2; };
// std::unique_ptr 들이 가리키는 Widget 객체들을 비교
auto derefUPLess =
[] (const std::unique_ptr<Widget>& p1,
const std::unique_ptr<Widget>& p2)
{ return *p1 < *p2; };
// C++14 버전 :
// 그 어떤 것이든 포인터처럼 작동하는 것들이 가리키는 값들을 비교
auto derefUPLess2 =
[] (const auto& p1,
const auto& p2)
{ return *p1 < *p2; } ;
또한 auto 는 "형식 단축(type shortcut)" 과 관련된 문제를 피할 수 있다. 예시를 보자.
std::vector<int> v;
// v.size() 의 공식적인 반환 형식은 std::vector<int>::size_type 임
unsigned sz = v.size();
// 하지만 64 비트 Windows 에서는 unsinged 가 32 비트인 반면,
// std::vector<int>::size_type 은 64 비트로, 오작동 가능성이 있다!
// 이식성 문제 해결
auto sz2 = v.size();
이는 이식성과도 연관이 된다.
마지막으로, auto 를 사용하지 않으면 오히려 안되는 경우를 보자.
std::unordered_map<std::string, int> m;
for (const std::pair<std::string, int>& p : m)
{
// do something
}
위 코드에서, 키 부분에 const 가 붙었으므로, 해시 테이블에 담긴 std::pair 의 형식은 std::pair<std::string, int> 가 아니라 std::pair<const std::string, int> 이다. 컴파일러는 std::pair<std::string, int> 객체를 std::pair<const std::string, int> 객체들로 변환하려 든다. 각 반복에서 컴파일러는 p 형식의 임시 객체를 생성하고, m 의 각 객체를 복사하고, 참조 p 를 그 임시 객체에 묶음으로써 그러한 변환을 실제로 수행한다. 그 임시 객체는 루프 반복의 끝에서 파괴된다.
auto 를 사용하면 어떨까?
std::unordered_map<std::string, int> m;
for (const auto& p : m)
{
// do something
}
p 의 주소는 실제로 m 안의 한 요소를 가리키는 포인터의 주소이다. 이는 효율적이고 타자도 더 쉽다.
'Tutorials > C++ : Advanced' 카테고리의 다른 글
Effective Modern C++ | 항목 7 : 객체 생성 시 괄호'( )' 와 중괄호'{ }' 를 구분하라 (0) | 2022.10.26 |
---|---|
Effective Modern C++ | 항목 6 : auto 가 원치 않은 형식으로 연역될 때는 명시적 형식의 초기치를 사용하라 (0) | 2022.10.26 |
Effective Modern C++ | 항목 4 : 연역된 형식을 파악하는 방법을 알아두라 (0) | 2022.10.26 |
Effective Modern C++ | 항목 3 : decltype 의 작동 방식을 숙지하라 (0) | 2022.10.26 |
Effective Modern C++ | 항목 2 : auto 의 형식 연역 규칙을 숙지하라 (0) | 2022.10.26 |
Comments