views:

131

answers:

2

I'm a Java programmer and have recently needed to start coding in C++. I'm trying to port some Java code of mine that makes heavy use of the System.arraycopy method and want to know if there is an equivalent in C++. Basically I want to have n byte arrays and combine them into one big array. Each of the initial arrays can be of variable length, so I don't want to go through the hoops of calculating the end arrays length and then populating the entire array one position at a time as this feels rather slow and I'm sure this operation has been optimized. However, I can't find what this optimization is (although I may be making this more complicated than it should be).

Here's some pseudo (Java) code to illustrate what I want to do.

byte[] a = new byte[]{0x00, 0x01, 0x02};
byte[] b = new byte[][0x03, 0x04, 0x05];
byte[] ab = new byte[a.length+b.length];
System.arraycopy(ab, 0, a, 0, a.length);
System.arraycopy(ab, a.length+1, b, 0, b.length);
//Now, I would expect ab to look like {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}

Like I said, this may be simple in C++, but I will be doing this many, many times and want to make sure I'm doing it as efficiently as possible.

+2  A: 

Given a_len and b_len (containing the length in bytes of a and b), and a dst buffer big enough to hold both arrays, you can use memcpy. Note: this also depends on dst being declared as a pointer to byte size data.

memcpy( dst, a, a_len );
memcpy( dst+a_len, b, b_len );

This works well for primitive types (as it looks like you're copying byte arrays around)... If you need to copy objects, take a look at std::copy<>().

dicroce
std::copy will work just as well on primitive types.
Emile Cormier
This was also something I couldn't find in the documentation I was looking at, the fact that you can use memcpy() to place something at a certain location ( memcpy(dst+a_len, ...). Thank you.
Nolson
@Emile: As long as "just as well" doesn't include performance, you are correct. For primitive types `std::copy` will yield the same end result as `memcpy`, but not as quickly.
Ben Voigt
Surely, the library implementation must have specialized std::copy to perform a simple memcpy when T is a primitive type, no? If not, then the optimizer must see that the resulting std::copy code would be equivalent to memcpy?
Emile Cormier
Looking up `std::copy` in libstdc++, I found the following comment: "This inline function will boil down to a call to @c memmove whenever possible. Failing that, if random access iterators are passed, then the loop count will be known (and therefore a candidate for compiler optimizations such as unrolling). Result may not be contained within [first,last); the copy_backward function should be used instead."
Emile Cormier
@Ben: std::copy() will perform just fine.
janm
@Emile: Is that performance guarantee made in the standard, or are you generalizing from the comments in one particular version of one particular implementation? I agree that on a highly optimized implementation `std::copy` should become as fast as `memcpy`, but whenever there is a difference it's `memcpy` that's going to be faster.
Ben Voigt
@Ben: Is there a performance guarantee for memcpy? Why are you allowed to generalize on the performance of memcpy, while I'm not allowed to generalize on std::copy? ;-P
Emile Cormier
@Emile: You're right, that's only fair.
Ben Voigt
A: 

Try this:

#include <vector>

int main()
{
    typedef unsigned char Byte;
    std::vector<Byte> a;
    std::vector<Byte> b;
    // Fill vectors a and b

    std::vector<Byte> ab;
    // Reserve enough memory to fit a and b in order to avoid
    // unnecessary reallocations.
    ab.reserve(a.size() + b.size());
    ab.insert(ab.end(), a.begin(), a.end());
    ab.insert(ab.end(), b.begin(), b.end());

    return 0;
}

In C++, std::vector is your friendly neighborhood dynamically re-sizable array. It is just as fast as regular arrays for random access. It is well worth the time to study std::vector and other containers/algorithms in the standard library. I recommend the C++ standard library book by Josuttis.

vector::insert on vectors of basic types will probably be just as fast as doing C-style memcpy on C arrays. I'd be very surprised if it weren't.

Emile Cormier
Ah, vectors, thank you very much. I know there's not a 'straight' translation between Java and C++ as they are both very different languages. But, it's hard to ask the 'right' question when you don't know what you're really asking. So thank you for starting me down the path of the right way to do things in C++.
Nolson
No problem. Besides containers/iterators/algorithms, the most important "C++ way" thing to learn would be automatic memory management using smart pointers. Coming from a Java (with it's automatic garbage collection), you will truly appreciate their usefulness. I guarantee that the time you spend leaning smart pointers will pay for itself 10-fold in time saved chasing memory leaks and dangling pointer bugs.
Emile Cormier
For information on smart pointers, check out the Boost library: http://boost.org. In particular, `shared_ptr` and `scoped_ptr`. The Boost library is like the "secondary" standard C++ library with lots of neat, general-purpose goodies.
Emile Cormier
Probably you mean `ab.end()` in place of `c.end()`.
ArunSaha
@ArunSaha: Yes, thanks. Fixed.
Emile Cormier