spin_eight
spin_eight

Reputation: 4025

If I use the memcpy function to copy an array, what possible consequences: bottlenecks and perfomance changes?

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

Answers (3)

qPCR4vir
qPCR4vir

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

Mats Petersson
Mats Petersson

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

Roddy
Roddy

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

Related Questions