Notice : 内容無保証。禁無断転載。リンク不自由。

placement new

// placement new のサンプル
// 確保済みの領域に対してコンストラクトする

#include <iostream>

using std::cout ;
using std::endl ;

class Cresource {   // 確保/開放しなきゃならないリソースのシミュレート
private:
    static int  m_ct ;

    int m_i ;

public:
    Cresource(int i) : m_i(i) {
        m_ct++ ;
        cout << "Cresource(" << m_ct << ") : " ;
    }

    ~Cresource() {
        cout << "~Cresource(" << m_ct << ") : " ;
        m_ct-- ;
    }

    int i(void) const {
        return m_i ;
    }
} ;

int Cresource::m_ct = 0 ;

//

class C {   // placement new のサンプルクラス
private:
    Cresource*  m_pResource ;

public:
    C(int i=0) : m_pResource(new Cresource(i)) {
        cout << "(" << this << ")->C()" << endl ;

        if (i==-1){
            cout << "コンストラクタ中で例外発生" << endl ;
            throw "(例外発生のシミュレート)" ;
        }
    }

    ~C(void) {
        cout << "(" << this << ")->~C() : " ;
        delete m_pResource ;
    }

    //

    void show(void) {
        cout << "(" << this << ")->show() : C (" << m_pResource->i() << ")" << endl ;
    }

    //

    void* operator new(size_t s) {
        cout << "new = malloc(" << s << ") : " ;
        return malloc(s) ;
    }

    void operator delete(void* p) {
        cout << "delete = free(" << p << ") : " << endl ;
        if (p) free(p) ;
    }

    // placement new 本体

    void* operator new(size_t s, void* p) {
        cout << "new(" << s << ", " << p << ") : " ;
        return p ;
    }

    void operator delete(void* p, void* q){ // 直接は使ってない。コンストラクタで例外が発生した場合、自動的に呼ばれる
        cout << "delete(" << p << ", " << q << ")" << endl ;
    } ;
} ;

//

typedef char Tbuf[sizeof(C)] ;
static const int bufNum = 4 ;
static Tbuf buf[bufNum] ;       // 確保済みの領域のシミュレート
static C* const pC = (C*)buf ;  // 実際には 0x70000000 とか、コントロールしたいハード依存のアドレスを指定

//

static void init(void){
    cout << "\n[init()]" << endl ;

    for (int i=0 ; i<bufNum ; i++) {
        new (buf+i) C(10+i) ;   // placement new の使用。領域自体は既に確保されているので、コンストラクトだけする
    }
}

static void run(void){
    cout << "\n[run()]" << endl ;

    for (int i=0 ; i<bufNum ; i++) {
        (pC+i)->show() ;
    }
}

static void done(void){
    cout << "\n[done()]" << endl ;

    for (int i=0 ; i<bufNum ; i++) {
        (pC+i)->~C() ;
        cout << endl ;
    }
}

//

int main(void){
    cout << "\n" << buf << " <= buf < " << buf+bufNum << endl ;

    init() ;
    run() ;
    done() ;

    //

    cout << "\n[例外]" << endl ;

    try {
        new (buf) C(-1) ;
    }catch (char* e){
        cout << "例外をキャッチ : " << e << endl ;
    }catch (...){
        cout << "unknown exception" << endl ;
    }

    //

    return 0 ;
}