Reputation: 4025
I am trying to implement my container Vector for an educational purpose.
While implementing it`s method reserve I faced the question:
that is the best way of relocation of array of elements from one place in memory (initial capacity)
to the memory allocated for a new capacity?
I consider 2 possibilities: using loop or using c function memcpy.
Here is my implementation:
template <typename T>
void MyVector<T>::reserve(int elements)
{
if (m_size >= elements) // when no need to reserve memory as at least demanded amount of memory has been already allocated
return;
m_capacity = elements;
tmp = m_array;
// allocate needed amout of memory:
m_array = new T[elements];
// copy elements ???? can I use memcpy????
for (int i = 0; i < m_size; ++i)
{
m_array[i] = tmp[i];
}
delete tmp;
}
template <typename T>
void MyVector<T>::reserve1(int elements)
{
if (m_size >= elements) // when no need to reserve memory as at least demanded amount of memory has been already allocated
return;
m_capacity = elements;
tmp = m_array;
// allocate needed amout of memory:
m_array = new T[elements];
// copy elements ???? can I use memcpy????
memcpy(m_array, tmp, m_size);
delete [] tmp;
}
Questions:
- what bottlenecks should I take into account?
- what difference in performance?
- are there more efficient methods?
- can you advice my a source of info where implementation of STL containers described in depth (my aim is to made my own implementation and when compare with professional implementation in order to check my knowledge and to find out what areas need improvement)
Upvotes: 1
Views: 1367
Reputation: 3571
I agree with Roddy. But even worse. Even if you manage to free the old memory without invoking the destructor and the other memory is not freed, some object could contain references or pointers to internal parts, with will be broken anyway. Finally it would be good to know the consequences of the new memory alignment.(For T=char, memcpy will be probably the best).
If it works, forcing a move assignment in your for
can be the best solution. (you dont need the old copies)
Well, ultimately you can see how the std::vector is designed, with separate memory allocation, uninitialized and then in place initialized, copy or moved. Take a look at 19.4 Allocators, in The C++ Programming Language, Third Edition by Stroustrup.
Upvotes: 0
Reputation: 129364
There are performance aspects as well as other factors where copying an object using memcpy
and "simple loop" method will make a difference. For example:
class Blah
{
Blah()
{
some_function(this);
}
};
MyVector<Blah> v;
...
Now, if some_function
stores this
in some way [for whatever good or bad reason], your reserve1
will cause it to be deleted, but the reference to this
will remain pointing to the deleted object. Which is probably not what you wanted.
The same of course applies if the object contains any object that uses allocation internally - for example std::string
.
Upvotes: 1
Reputation: 68033
You can't use memcpy
because non-trivial objects may contain pointers to other blocks of memory.
Consider a vector of std::string
: Each is typically implemented as a small object containing a pointer to a dynamically allocated array of chars. If you memcpy
the strings, you make a copy of the pointers but not of their actual character data. But the ownership of those pointers is not transferred. So when you delete the original array (which calls the destructors for all those strings) their memory is freed, and your 'new' objects all have dangling pointers.
Using std::copy
is a better way of achieving this.
Upvotes: 5