vectorとunique_ptr その3
vectorはコピーを使う、だからauto_ptrとおなじくunique_ptrは使えない。
以下のコードはコンパイルエラーが発生する。
vector<unique_ptr<C> > v; v.push_back( unique_ptr<C>( new C ) );
まれに、このコードをおすすめするHPが見られるが、コンパイルできるコンパイラーがあるのだろうか?
コンパイルできたとしても、今まで見てきたように、sortなどで副作用が出るので行うべきではない。
C++11対応のコンパイラーであれば、push_backの代わりにemplace_backが使えるかもしれないが、セットは可能でも、やはりsortで問題が発生する。
対処方法はやはりshared_ptrに置き換えればよい。
vector< shared_ptr<C> > v; v.push_back( shared_ptr<C>( new C ) );
shared_ptrのコストを避けようとするのであれば、削除に備える必要がある。
typedef std::vector<unique_ptr<C> > Vip; typedef std::vector<unique_ptr<C> >::iterator Vip_itr; typedef std::vector<unique_ptr<C> >::const_iterator Vip_citr; class D { void _clear( Vip_itr iSt, Vip_itr iEd ) { for( ; iSt < iEd; ++iSt ) { if( *iSt ) delete *iSt; } } void _copy( Vip &dst, Vip_citr iSt, Vip_citr iEd ) { for( ; iSt < iEd; ++iSt ) { dst.push_back( new int(**iSt) ); } } public: D() {}; D( const C& lhs ) { _copy( v, lhs.v.begin(), lhs.v.end() ); } Vip v; void resize( unsigned int size ) { if(size<v.size()) _clear( v.begin()+size-1, v.end() ); } Vip_itr erase( Vip_itr itr ) { if( ( itr != v.end() )&&( *itr ) ) delete *itr; return v.erase( itr ); } void clear() { _clear( v.begin(), v.end() ); } };
D v;
v.v.push_back(unique_ptr<C>(new C));
これでも抜けがあるかもしれない。実際、重複したポインター参照などを考慮していない。vectorをそのまま使えないことも問題があるだろう。
文芸的にはよいかもしれないが、実践的ではないと思う。