Pichuu64
Pichuu64

Reputation: 83

Is using memcpy() in this way bad practice?

I'm messing around with arrays and attempting to find efficient ways of performing operations on the data.

Adding values at the end is easy enough but shifting the data on or more indexes back has drawbacks. I could potentially create an new array with sufficient space and copy the data starting at the shifted index and then delete the original and swap the pointers but I believe this method is memory inefficient.

I ended up stumbling upon utilizing memcpy() on the array itself assuming there's space in it for the shift and it worked beautifully, however I am concerned that it's not proper or if I'm doing the same thing only that not consciously.

My code looks like this

const int size = 25, buffer = 25;

int num[size+buffer]{}; 
initialize(num, size);


cout << "Values:" << endl;
print(num, size+buffer);
cout << endl << endl;

memcpy( &(num[size]), num, sizeof(int) * size );

cout << "Values:" << endl;
print(num, size + buffer);
cout << endl << endl;

initialize is a function to assign values from a file and its a simple for loop; By the second print function the array holds two copies of the values. If everything works as I think it is I'm thinking of shifting it the amount needed for the new values and then inserting them there. Seems clean and quick and hopefully memory efficient.

I would appreciate any feedback.

Upvotes: 2

Views: 1612

Answers (2)

Den-Jason
Den-Jason

Reputation: 2573

You could probably implement it more efficiently by using a std::deque which is optimised to allow insertion and removal of items at the beginning and end. https://en.cppreference.com/w/cpp/container/deque

Although we could disappear down a bolt-hole in terms of algorithms etc, the nub of your question is, "is this considered bad practice". The answer to that is clearly "yes"; the modern philosophy is to write "expressive code". If you think that expressive code may be inefficient, and that working "close to the metal is best", check out Matt Godbolt's talk at CppCon 2017 in terms of how much optimisation compilers do for you. The message is clear; don't write "clever optimised code", just be clear and expressive about intent with the source, and let the compiler do the optimisation for you: https://www.youtube.com/watch?v=bSkpMdDe4g4

Another thing to consider is that a lot of algorithms are ranked according to Big O Notation, which implies that some inefficient algorithms should never be used. However, some of the so-called inefficient algorithms are better in terms of locality of reference; particularly if you're using small amounts of data that fits within a cache line. Linked lists will most likely jump around memory, leading to cache misses. Check out this presentation: https://www.youtube.com/watch?v=fHNmRkzxHWs

As suggested in the comments, also check out the following video about data structures (this link skips the first 8 minutes, because they are unimportant): https://youtu.be/4IrUAqYKjIA?t=525

Upvotes: 2

Zan Lynx
Zan Lynx

Reputation: 54325

You ought to just use std::vector. If it is storing a POD (plain old data) type it will optimize to use memmove. (Note: Using memcpy as you are doing is not allowed on overlapping data. Things will break. When you least expect them.) And if it is storing a more complex type, it will do all of the proper extensions, copies, moves or swaps.

Upvotes: 0

Related Questions