Re: C++0x コンストラクタの引数をとる push_back
http://d.hatena.ne.jp/faith_and_brave/20080310/1205149207
なんでメモリリークするのかは考えてもらう(笑)として、検証用にアロケータを作成したので貼っておきます。
#include <boost/config.hpp> #include <memory> bool allocated = false; template<class T> class once_allocator; template<> class once_allocator<void> { public: typedef void* pointer; typedef const void* const_pointer; typedef void value_type; template <class U> struct rebind { typedef once_allocator<U> other; }; }; template<class T> class once_allocator { public: typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef T value_type; template <class U> struct rebind { typedef once_allocator<U> other; }; once_allocator() throw() { } once_allocator(const once_allocator&) throw() { } template <class U> once_allocator(const once_allocator<U>&) throw() { } ~once_allocator() throw() { } pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } pointer allocate( size_type n, once_allocator<void>::const_pointer hint = 0) { if (allocated) throw std::bad_alloc(); T* p = static_cast<T*>(::operator new(n * sizeof(T))); allocated = true; return p; } void deallocate(pointer p, size_type n) { ::operator delete(static_cast<void*>(p)); } size_type max_size() const throw() { return 1; } void construct(pointer p, const T& val) { new(static_cast<void*>(p)) T(val); } #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) template<class... Args> void construct(pointer p, Args&&... args) { new(static_cast<void*>(p)) T(args...); } #endif void destroy(pointer p) { p->~T(); } }; template<typename T> inline bool operator==(const once_allocator<T>&, const once_allocator<T>&) { return true; } template<typename T> inline bool operator!=(const once_allocator<T>&, const once_allocator<T>&) { return false; }
あとは、vectorの要素型のデストラクタで何か出力すれば確認できます。
using namespace std; struct person { int age; string name; person(int age, const string& name) : age(age), name(name) { cout << static_cast<void*>(this) << " person::person(int,const string&)" << endl; } ~person() { cout << static_cast<void*>(this) << " person::~person()" << endl; } }; int main() { try { vector<shared_ptr<person>,once_allocator<shared_ptr<person>>> v; v.reserve(1); // before v.push_back(shared_ptr<person>(new person(43, "Kikuko"))); // after v.push_back(new person(17, "Kikuko")); } catch (const std::exception& e) { cerr << "Error: " << e.what() << endl; } return 0; }
実行結果
0x1170300 person::person(int,const string&)
0x1180348 person::person(int,const string&)
0x1170300 person::~person()
Error: vector::_M_insert_aux
ちなみに、上のテストコードは空ベクタのcapacity()が0かつ、reserve()で要求サイズきっかり確保する実装じゃないと動きません。あしからず。
#エラーメッセージ見る限り、bad_allocより前にmax_size()のチェックに引っかかっているっぽいですね。