c++ - reserve() Implementation for std::vector in STL -


consider implementation of std::vector::reserve() book "the c++ programming language, 4th ed., bjarne stroustrup:

template<class t, class a> void vector<t,a>::reserve(size_type newalloc) {     if (newalloc<=capacity()) return;     vector_base<t,a> b {vb.alloc,newalloc};          // new storage                                                      // (see ps of question details on vb data member)      t* src  = elem;                                  // ptr start of old storage     t* dest = b.elem;                                // ptr start of new storage            t* end  = elem+size();                           // past-the-end ptr old storage     (; src!=end; ++src, ++dest) {         new(static_cast<void*>(dest)) t{move(*src)}; // move construct         src–>~t();                                   // destroy     }      swap(vb,b);                                      // install new base (see ps if needed) } // implicitly release old space(when b goes out of scope) 

note in loop, each element in vector, @ least 1 call made ctor , dtor(possibly triggering more such calls if element's class has bases, or if class or bases have data members ctors). (in book, for-loop separate function, injected reserve() here simplicity.)

now consider suggested alternative:

template<class t, class a> void vector<t,a>::reserve(size_type newalloc) {     if (newalloc<=capacity()) return;     vector_base<t,a> b {vb.alloc,newalloc};    // new space      memcpy(b.elem, elem, sz);                  // copy raw memory                                                // (no calls ctors or dtors)      swap(vb,b);                                // install new base } // implicitly release old space(when b goes out of scope) 

to me, seems end result same, minus calls ctors/dtors.

is there situation alternative fail, , if so, flaw?


p.s. don't think relevant, here data members of vector , vector_base classes:

// used data member in std::vector template<class t, class = allocator<t> > struct vector_base {                    // memory structure vector      alloc;       // allocator      t* elem;       // start of allocation      t* space;      // end of element sequence, start of space allocated possible expansion      t* last;       // end of allocated space       vector_base(const a& a, typename a::size_type n)          : alloc{a}, elem{alloc.allocate(n)}, space{elem+n}, last{elem+n} { }      ~vector_base() { alloc.deallocate(elem,last–elem); } // releases storage only, no calls                                                            // dtors: vector's responsibility              //... };  // std::vector template<class t, class = allocator<t> > class vector {      vector_base<t,a> vb;            // data here      void destroy_elements(); public:      //... }; 

this might fail:

  • memcpy() work if have vector of pod.

  • it fail other kind of objects doesn't respect semantic of objects copies (copy construction).

example of issues:

  • if constructor of object sets internal pointers internal members, memcpy() copy value of original pointer, not updated correctly , continue point memory region released.
  • if object contains shared_ptr, object count become inconsistent (memcpy() duplicate pointer without incrementing reference count, swap() make sure original shared pointer in b, released, shared pointer reference count decremented).

as pointed out t.c in comments, vector stores non-pod data memcpy() results in ub (undefined behaviour).


Comments

Popular posts from this blog

get url and add instance to a model with prefilled foreign key :django admin -

css - Make div keyboard-scrollable in jQuery Mobile? -

ruby on rails - Seeing duplicate requests handled with Unicorn -