Reputation: 76240
Context
I'm trying to implement my version of the std::vector
template class. The vector contains a dynamic array of the template argument T
:
_vec = new T[n];
Obviously T
can be any type at all, pointers, classes, primitive types. When one call v.resize(4)
on a vector of size 6
it should obviously remove the last 2 elements of the dynamic array (without reallocating the array) following this specification:
If n is smaller than the current container size, the content is reduced to its first n elements, removing those beyond (and destroying them).
By destroying I mean, and I think the std library means, calling the destructor for object or simply deallocating the memory space if it is any other primitive type including pointers.
Question: Is it possible (and if so, how) destroy template elements in a dynamically allocated array without deallocating and reallocating it?
What have I tried? Well, I sincerely don't know where to start:
delete
on primitive types. T
is not an object. _size
counter (so that an a future push_back
the elements would be overwritten), but that wouldn't immediately call the destructor for the object.Upvotes: 1
Views: 849
Reputation: 21749
FredOverflow is right about object allocation.
According your question, all you need to do is just distinguish objects from non-objects (scalars). There is a real code from <xmemory>
in Visual Studio 2010 distribution:
template<class _Alloc> inline void _Destroy_range(
typename _Alloc::pointer _First, typename _Alloc::pointer _Last, _Alloc& _Al);
template<class _Alloc> inline void _Destroy_range(
typename _Alloc::pointer _First, typename _Alloc::pointer _Last, _Alloc& _Al,
_Nonscalar_ptr_iterator_tag); // Object overload
template<class _Alloc> inline void _Destroy_range(
typename _Alloc::pointer _First, typename _Alloc::pointer _Last, _Alloc& _Al,
_Scalar_ptr_iterator_tag); // Non-object overload
They use simple dispatching with a special flag, which can be computed using some traits class.
Upvotes: 0
Reputation: 40603
When you are implementing a vector
, you probably want to keep the management of the storage and the management of the objects separate.
Storage is managed using allocator::allocate(size_type n)
and allocator::deallocate(pointer p, size_type n)
, which are typically implemented as return ::operator new(n * sizeof (T));
and ::operator delete(p);
respectively.
These functions allocate and deallocate memory, but do not call constructors or destructors for objects contained in that memory.
Object lifetimes are managed using allocator::construct(U* p, Args&&... args);
and allocator::destroy(U* p);
, which are typically implemented as ::new((void *)p) U(std::forward<Args>(args)...);
and p->~U()
respectively.
These functions construct and deconstruct objects in preallocated memory, but do not themselves manage the memory.
Upvotes: 2
Reputation: 263118
new T[n]
is not what you want, because that will already create n
objects of type T
, but you only want to allocate memory for up to n
objects of type T
.
You may want to read up on placement-new syntax and placement-delete syntax. Wikipedia
Upvotes: 1