항목 6 : 임시 개체들 (난이도 5)
불필요하거나 임시로 사용되는 개체들은 작업을 매우 어렵게 만들거나(임시 개체에 작업할수 있다는 위험성) 성능을 떨어뜨리는 주요 요인이다.(불필요한 복사 생성자 호출로 인한 오버헤드) 이런것들이 어떤 것들이 있는지 알아보자
예제 코드~
자.. 여기에 최소한 3개의 불필요한 개체들을 만들어 내고 있다. 찾아 보아라~
분석
이 코드를 보고 어떤 사람을 구역질을 낼 수도 있다. .. 왜냐하면 emps 로 받을때 list 전부를 복사해야 할테니까 말이다. 또한
string 객체도 여러 char 들의 집합이기 때문에 list와 다를게 없다. 전부 const& 받아 처리 하자.
반환을 std::string 으로 하는건 좀 그렇지만, .. 일단 살포시 무시하고 넘어간다.
여기서 i != emps.end(); 를 사용하는데 값이 변경될 일이 없는건 미리 평가하여 값을 저정하고 저장된 값으로 쓰는게 좋다. 또한 i++ 이 부분은 후위 연산자를 이용하여 iterator 를 증가시킨다. 이게 왜 문제이냐면 후위연산자 구현을 어떻게 해 놓은지 보도록 하자.
이것이 iterator의 후위연산자이다. _Tmp 에 현재 iterator를 복사하고, 전위연산으로 자신을 증가 한 다음 복사된 iterator를 반환하면서 구현되어 있다. 이것은 iterator에만 국한되지 한고 전반적인 C++ 에서 관례처럼 통한다. 전위 연산를 위주로 하고, 후위연산은 필요할 때 사용해야 한다.
이 부분도 Emplyee 클래스가 처리되기 위해선 string 객체를 반환되는
처리(operator std::string)나 operator==(std::string rhs) 등이 구현되어 있어야 한다. 이때도 중요하게
const& 로 받아 처리 되는 식으로 바꾸어야 한다(잠재적인 문제까지 경고해주는 셔터씨의 센스는 놀랍다)
이 두개의 코드때문에 std::string 을 반환할 수밖에 없다. 이것을 최적화 하기 위해선 위에 만저 std::string ret; 를 선언하고 return ret; 형식으로 하는게 약간 더 빠를 수 있다고 하지만, 결과적을 std::string 을 뱉어야 한다는건 변하지 않는다.
마지막으로..
이것을 다시보면 std::string 을 뱉는다. 이게 바로 큰 문제다. 위의 코드 때문에 어쩔수 없다. 지역객체를 const& 로 반환할 수도 없는 노릇이고, static std::string 으로 내부 변수를 반환해도 .. 외부에서 변경 되면, 또 잠재적인 문제로 연결 되어 진다. (빈대 잡으려다 집에 불 붙이는 꼴이다..,)
해결코드
총평
Effective C++ 을 봐서인지 .. 쉽게 찾고 쉽게 변경할수 있었다. 책에는 반환값을
std::string 으로 하는데, 실제론 const std::string 으로 반환해야 더 좋지 않을까 한다. 음.. 느낌으론 보다가 "결국
여기까지가 .. 한계"라고 생각 되었다. 왜냐하면, std::string 를 반환하게 하는건 바꿀수가 없었기 때문이다. 어떻게 하면 알고리즘이
머리에서 똑똑 나오게 될까?