copy arrays

Started by
35 comments, last by s_p_oneil 18 years, 9 months ago
Quote:Original post by Dave Hunt
Quote:Original post by Fruny
me22 got it right. There is little reason to use memcpy() anymore, std::copy() is infinitely superior.


Not quite infinite. It's 9 characters to type instead of 6. [smile]


I disagree. If you're using C++, you should be using <cstdlib>, and thus std::memcpy would be used instead of simply memcpy - which adds up to 11 characters, not 6.

"stdlib.h allows simply memcpy" you say?
"using namespace std; allows simply copy" I retort (making std::copy simply "copy", 4 characters).

They're the same in terms of namespace polution, I'd argue.
Advertisement
Quote:Original post by me22
A good implementation will implement that, for PoD types, as a memcpy, but will do the right thing if you change index1 and index2 to arrays of non-PoD types.


In reality its more likely to dispatch at compile-time to use memmove, not memcpy, because the input and output ranges are permitted to overlap. It is still much better than explicit loop code.

To be more specific, a typical implementation of std::copy will dispatch (type and/or tag) at compile-time from the following:


  1. memmove whenever possible, normally the case when the iterator category is random access iterators and the value type is a POD-type

  2. Failing that, if random access iterators are passed and the value type is NON POD-type, then the loop count will be known (and therefore a candidate for compiler optimizations such as unrolling).

  3. Failing all of the above then the most generic copy is used



Note this happens all at compile-time so this selection doesn't exist at run-time and its typically all inlined away when optimizations are on.

Yes i suggest you use the C++ standard library algorithms because it handles cases you would never have thought of, besides you shouldn't use C memory rountines directly on NON POD-types.

[Edited by - snk_kid on June 30, 2005 10:27:09 AM]
Quote:Original post by ApochPiQ
Premature optimization is the root of all evil.


1. I strongly disagree. Sloppy/messy/unmaintainable code is much worse, whether it's optimized or not. Only premature operations that make the code sloppy, messy, or difficult to maintain are a problem (i.e. unrolling loops, converting code to assembler). If it makes the code cleaner, it's a good thing.

2. Since when is using memcpy an optimization? It's been the de-facto standard way to copy contiguous blocks of memory in C since the language was invented. (Although I agree that it seems like overkill for copying 3 elements.)

3. Unless Christoph knows STL and the new C++ standard extensions, he should stick with the standard C version of memcpy until he's ready to jump into STL.

Quote:Original post by s_p_oneil
Quote:Original post by ApochPiQ
Premature optimization is the root of all evil.


1. I strongly disagree.


Perhaps (to get closer to the oft-misquoted original) "Premature optimization is the root of all kinds of evil" would be a more accurate statement.
Quote:Original post by s_p_oneil
2. Since when is using memcpy an optimization? It's been the de-facto standard way to copy contiguous blocks of memory in C since the language was invented. (Although I agree that it seems like overkill for copying 3 elements.)


memcpy is typically more efficent than a hand-written loop, but he is using C++ so in general he should be use C++ algorithms therefore std::copy.

Quote:Original post by s_p_oneil
3. Unless Christoph knows STL and the new C++ standard extensions, he should stick with the standard C version of memcpy until he's ready to jump into STL.


Okay let him use memcpy on a array of NON-POD types and see what will happen. The best way to learn C++ is to learn it the wright way from the beginning which means learning to use the C++ standard library with C++ which has little to do with efficiency but they are written to be as a efficient + safe as possiable.
Quote:Original post by s_p_oneil
1. I strongly disagree. Sloppy/messy/unmaintainable code is much worse, whether it's optimized or not. Only premature operations that make the code sloppy, messy, or difficult to maintain are a problem (i.e. unrolling loops, converting code to assembler). If it makes the code cleaner, it's a good thing.


Generally speaking, when a programmer knows enough about when to optimize and clean up code, they don't need to ask for the fastest way to copy memory. In my experience, it is quite rare for optimizations to make code cleaner. Distinguish optimization and refactoring.

IMHO, a memcpy() call with explicit address taking and sizeof() juggling is messier than a simple loop. Short is not equivalent to clean.


Quote:Original post by s_p_oneil
2. Since when is using memcpy an optimization? It's been the de-facto standard way to copy contiguous blocks of memory in C since the language was invented. (Although I agree that it seems like overkill for copying 3 elements.)


I didn't say anything about memcpy being an optimization. My point was to the original poster: worrying about how long it takes to copy some array elements is not productive in the majority of cases. It is very rare for a data copy to be a serious performance bottleneck, and if it is, there is a very strong chance that the best optimization is algorithmic and high-level, not a "faster version of memcpy."

In the case of copying ints, memcpy() won't be any faster than a simple loop, because they both move memory in DWORDs (at least if the memcpy() implementation is the way it was several years ago when I last looked at it). On a 32-bit platform, in general, there isn't a faster way to copy memory blocks than in 32-bit chunks. In the case of complex data (structures, classes, strings, etc.) then certainly memcpy() will tend to be superior. In any case my point wasn't that an explicit loop is faster necessarily, but that the speed is almost certainly irrelevant and the simpler, more readable solution is preferable.

Quote:Original post by s_p_oneil
3. Unless Christoph knows STL and the new C++ standard extensions, he should stick with the standard C version of memcpy until he's ready to jump into STL.


I fully agree with this. Do the simplest thing that could possibly work.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Quote:Original post by MaulingMonkey
They're the same in terms of namespace polution, I'd argue.
Not IMO. memcpy is something cryptic you very likely wouldn't use as a function/method/whatever name yourself, whereas copy is clear english and nice and short, so it might very well be used.
Quote:Original post by Anonymous Poster
Quote:Original post by MaulingMonkey
They're the same in terms of namespace polution, I'd argue.
Not IMO. memcpy is something cryptic you very likely wouldn't use as a function/method/whatever name yourself, whereas copy is clear english and nice and short, so it might very well be used.


When you include stdlib.h, or use the entire std namespace, you get much more than just memcpy, hence the problem.

I've run into clashes with (std::)system() vs my own system class before, the fact is that there's plenty of names you might want to use in stdlib.h

It dosn't matter if it's 20 or 100, fact is, the namespace will be poluted, period.

My solution has generally been to never write anything in the global namespace. The implementation of main usually follows this layout in my projects:
namespace project_name {    int main ( int argc , char * argv[] );}int main ( int argc , char * argv[] ) {    return project_name::main( argc , argv );}


EDIT: DD edited out his post after the fact it'd seem, which I realized as I started to merge two consecutive posts by myself into one... I feel like keeping my comment on the matter though:

Quote:Original post by DigitalDelusion
one could even be so bold as to advice making the code truly selfdocumenting and mind numbingly obvious by doing:

template <typename SrcItr, typename DstItr>inline DstItr copy_n(SrcItr first, DstItr out, typename std::iterator_traits<SrcItr>::difference_type count){    return std::copy( first, first + count, out);}


Bad idea IMO, argument order is not intuitive to me, plus it goes against existing practice as set by SGI (linky) where count is the second, not the third, argument.
Quote:Original post by MaulingMonkey
EDIT: DD edited out his post after the fact it'd seem, which I realized as I started to merge two consecutive posts by myself into one... I feel like keeping my comment on the matter though:

Quote:Original post by DigitalDelusion
one could even be so bold as to advice making the code truly selfdocumenting and mind numbingly obvious by doing:

template <typename SrcItr, typename DstItr>inline DstItr copy_n(SrcItr first, DstItr out, typename std::iterator_traits<SrcItr>::difference_type count){    return std::copy( first, first + count, out);}


Bad idea IMO, argument order is not intuitive to me, plus it goes against existing practice as set by SGI (linky) where count is the second, not the third, argument.


I edited it out because I realized it was a bad idea since it was modled after the first response (using memcpy) instead of after the initial request (copying element 5 to 8) so I answered the wrong question.

I also got to grips with that the addition isn't sure to work effectivly and yeah it was a total brainfart on my part.

HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Quote:Original post by DigitalDelusion
I also got to grips with that the addition isn't sure to work effectivly and yeah it was a total brainfart on my part.


Either it is effective, or it isn't provided. That's why you got std::advance.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan

This topic is closed to new replies.

Advertisement