--/--/--

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

2009/06/03

template とコピーコンストラクタ

参照カウント方式でポインタの破棄タイミングを管理するスマートポインタ、いわゆる shared_ptr を実装しててはまった。コピーコンストラクタはコピーコンストラクタで素直に用意しておきましょうという話。

はじめ、T 型に代入可能な U 型の shared_ptr を受け入れるコンストラクタを用意していた。つまりこんな感じ。

template<class T>
class shared_ptr
{
    template<class U>
    shared_ptr(const shared_ptr<U>& src);
};

もちろんこのコンストラクタの中では、カウントとポインタの共有、そして最も重要な参照カウントのインクリメントが行なわれる。T 型同士の時でも、なんとなく呼ばれそうだし、コピーコンストラクタの代用になりそうだ。しかし、これはまずい。

vector<shared_ptr<Foo> > v;
v.push_back(shared_ptr<Foo>(new Foo()));

一見問題ないように見えるけど、問題ありあり。というのも上で宣言した shared_ptr のコンストラクタが呼ばれなくて、デフォルトのコピーコンストラクタが呼ばれてしまう。普通のコピーコンストラクタが呼ばれれば、当然参照カウントのインクリメントもされない。参照カウントがインクリメントされなければ new した Foo も即刻破棄される。v には期待したオブジェクトではなく、 ラップした Foo が削除された、shared_ptr の残骸が残っているだけ。

じゃあどうすりゃいいのかと言うと、冒頭に述べたとおり、素直に普通のコピーコンストラクタを用意する。というかそもそもコピーコンストラクタってこのシグネチャ(値か参照か、const か非 const かは関係なかったような)しか認められないのかな。

template<class T>
class shared_ptr
{
    shared_ptr(const shared_ptr& src); // 追加
    template<class U>
    shared_ptr(const shared_ptr<U>& src);
};
スポンサーサイト

comment

post




上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。