방프리

17.10.23. Effective C++ 4. 설계 및 선언 (항목25) 본문

C++/Effective C++

17.10.23. Effective C++ 4. 설계 및 선언 (항목25)

방프리 2020. 1. 14. 21:08

항목 25 : 예외를 던지지 않는 swap에 대한 지원도 생각해보자

 

- swap은 개발자들도 다들 알다싶히 값을 서로 교환하는 알고리즘을 말합니다.

딱히 알고리즘이라고 말하기도 뭐한... 그런 함수이죠

가장 기초적인 함수가 왜 이 항목에서 등장할까요?

필자는 STL에 이 함수가 포함된 이래, 예외 안전성 프로그래밍에선 없어선 안될 감초 역활로써,

자기 대입 현상의 가능성에 대처하기 위한 대표적인 매커니즘으로서 널리 사랑받아왔다고 설명합니다. 

그러면서 이 swap 함수를 사용하면서 비용을 복사라는 비용을 지불하게 되는데 이 항목에서

그 비용을 지불하지 않는 방법을 설명해줍니다. 

바로 다른 타입의 실제 데이터를 가리키는 포인터가 주성분인 타입의 객체(pimpl<pointer to implementation>)을

소개해주는데요.

이런 객체 전용의 함수를 제작하는 방법은 다음과 같습니다.

(1) std::swap 함수에 알려줍니다.

std::swap을 사용자 정의 클래스에 대해 특수화를 하는 것입니다.

바로 완전 템플릿 특수화를 사용하는 것인데 이 방법은 굉장히 추천드리지 않습니다.

왠만하면 사용하지 말라고 저자도 말리는군요

(2) 표준에서 제공하는 swap이 사용자 정의 클래스 및 클래스 템플릿에 대해 납득할만한 효율을 보인다면, 

아무것도 하지 않는 것이 좋습니다.

(3) 표준 swap의 효율이 기대한 만큼 충분하지 않으면 아래와 같이 하면 됩니다.

    1) 객체의 멤버 함수에 swap이라는 이름을 만들고, 이것을 public 멤버함수로 두며, 예외를 던지지 않으면 됩니다.

    2) 우리가 정의한 클래스 및 템플릿이 들어있는 네임스페이스와 같은 네임스페이스에 비멤버 swap을 만들어 넣고,

       멤버 함수의 swap 함수를 호출하여 처리하도록 합니다.

    3) 새로운 클래스를 만들고 있다면, 그 클래스에 대한 std::swap의 특수화 버전을 준비해두고, 이것도 swap

멤버 함수를 호출하도록 만듭니다.

(4) 사용자 입장에서 swap을 호출할 때, swap을 호출하는 함수가 std::swap을 볼 수 있도록 using 선언을

반드시 포함시킵니다. 그 다음에 swap을 호출하되 네임스페이스 한정자를 붙이지 않도록 합니다.

 

이것만은 잊지 말자!

* std::swap()이 여러분의 타입에 대해 느리게 동작할 여지가 잇다면, swap 멤버 함수를 제공하고,

   예외를 던지지 않도록 만듭시다.

* 멤버 swap을 제공했으면, 이 멤버를 호출하는 비멤버 swap도 제공합니다. 클래스(템플릿이 아닌)에 대해서는,

  std::swap도 특수화해 둡시다.

* 사용자 입장에서 swap을 호출할 때는, std::swap에 대한 using 선언을 넣어 준 후에 네임스페이스 한정 없이 

  swap을 호출합시다.

* 사용자 정의 타입에 대한 std 템플릿을 완전 특수화하는 것은 가능합니다. 그러나 std에 어떤 것이라도 새로 '추가'

  하려고 들지는 마십시오.

Comments