예외를 던지지않는 swap(effective c++ 25)

2015. 8. 25. 17:40프로그래밍/Effective C++

728x90
728x90

표준 제공 swap

복사만 제대로 지원하는 타입이면 어떤 타입의 객체이든 맞바꾸기 동작을 수행한다.


성능
swap의 내부에 객체를 넘기면 얄짤 없이 복사가 세 번이 일어난다. (엄청난 비효율)

pimpl기법

pointer to implementation이란 뜻으로 객체가 실제 데이터를 모두 가지고 있는 것이 아니라 

이를 가리키는 포인터로 설계하는 기법.


비효율적 swap 호출



한번 복사에 복사 생성자와 대입연산자가 여러 번 호출한다. 

특히 pImpl 기법이 사용되었다면 극도로 비효율적인 작업이 된다.


특수화 템플릿 swap


클래스의 swap으로 데이터가 가리키는 포인터만 서로 교환한다.

Wiget2의 완전 특수화 템플릿을 구성해주어 해당 클래스가 호출 될 때 이 특수화 함수가 호출 되도록 한다.

클래스 템플릿 swap


C++은 함수 템플릿에 대해선 부분 특수화를 허용하지만 클래스 템플릿에 대한 부분 특수화는 허용하지 않는다.


이렇게 함수 템플릿의 오버로딩으로 해결할 수 있다.


하지만! 이것도 컴파일 에러!!!! std는 템플릿에 대한 완전 특수화는 지원하지만

새로운 템플릿을 추가하는 것은 허용하지 않는다.


그러면 도데체 어떻게?

맴버 swap을 호출하는 비맴버 함수를 만들고, 이를 std::swap의 특수화 버전이나 오버로딩으로 선언하지 않는다.


이렇게 하면 된다!!


함수 사용법

using std::swap을 통해
T타입 전용 버전이 없다면 std 일반형 버전으로, T 타입 전용 버전이 있다면 그것이 호출 되도록 할 수 있다.

해당 코드가 없다면 호출하는 함수는 세 개 중 하나이다.(불분명) 
std에 있는 일반형(이것은 확실히 있다.)
std의 일반형을 특수화한 버전(있을 수도 있고, 없을 수도 있다.)
T타입 전용 버전(있을 수도 있고, 없을 수도 있다.)

정리
- std::swap이 구현 시 느리게 동작할 여지가 있다면 swap 멤버 함수를 제공하자. 
이 swap은 예외를 던지지 않도록 만든다.
- 멤버 swap을 제공한다면, 이 멤버를 호출하는 비멤버 swap도 제공하자. 
클래스(템플릿 아님)에 대해서는, std::swap도 특수화한다.
- 사용자 입장에서 swap을 호출할 때는, std::swap에 대한 using 선언을 넣어 준 후에 
네임스페이스 한정 없이 swap을 호출하게 하자.
- 사용자 정의 타입에 대한 std 템플릿을 완전 특수화하는 것은 가능하다. 
하지만 std에 어떤 것이라도 새로 추가하려 들지 말자.


728x90
반응형