Fast Pimpl Idiom

Tags:

http://www.gotw.ca/gotw/028.htm

Pimpl Idiom[http://mkseo.pe.kr/blog/?p=841, http://www.gotw.ca/gotw/024.htm]의 단점은 1) heap 메모리 할당과 해제, 2) 포인터를 사용한 호출입니다.

그 중, 메모리 할당과 해제를 해결하기 위한 첫번째 시도:

// file y.h
class Y {
    /*...*/
    static const size_t sizeofx = /*some value*/;
    char x_[sizeofx];
};

// file y.cpp
#include "x.h" // Pimpl Implementation class or struct

Y::Y() {
    assert( sizeofx >= sizeof(X) );
    new (&x_[0]) X;
}

Y::~Y() {
    (reinterpret_cast<X*>(&x_[0]))->~X();
}

그러나 이 방법은 char x_[sizeofx] 가 byte align을 안해준다는 문제, sizeofx 값을 사전에 알 수 없다는 문제가 있습니다. /* some value */ 자리에 sizeof(X)라고 쓰면 안되나? 라고 생각할 수 있지만, 그렇게 하려면 y.h 에서 #include “x.h”를 해서 X의 정의가 complete하게 만들어주어야합니다.

Herb Sutter가 제안한 방법은 fixed allocator를 정의하고, 그걸 상속받은 X를 만들란 것입니다.

struct FastPimpl {
  void* operator new( size_t s ) {
    return FixedAllocator::Instance()->Allocate(s);
  }
  void operator delete( void* p ) {
    FixedAllocator::Instance()->Deallocate(p);
  }
};

struct X: FastPimpl {
 ...
};

이러면 new와 delete의 오버헤드 문제가 해결되겠죠.