memcpy vs std::copy?

Hello everyone,
First off let me tell you what I am trying to achieve. I am trying to finish my packet class which takes in data and packs it nicely to be able to transfer it on the network.

I overload the << and >> operators to insert and extract data to and from a vector<char>. I would like to know if this is the right thing to do.

1. Should I use a vector at all or something else like char array with a fixed size etc... I was going with vector because I can re-size if needed.

2. If a vector is the best option should I use memcpy or std::copy?, I'm thinking std::copy would be better but in some cases it just messes up...

3. Is there a better way to do all is? look at the code below please.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
size_t inPos = 0;
Packet& Packet::operator << (const uInt32 & data)
{
     memcpy(&buffer[inPos], &data, sizeof(data));
     inPos += sizeof(data);
     return *this;
}

size_t outPos = 0;
Packet& Packet::operator >> (uInt32 & data)
{
     memcpy(&data, &buffer[outPos], sizeof(data));
     outPos += sizeof(data);
     return *this;
}


I had a std::copy version but it was messing up on large numbers and whatnot, if you have a better solution please share.
Last edited on
The difference between memcpy and std::copy is that memcpy copies bytes and std::copy copies any type, including user defined types.

If you used std::copy on data in those functions, it would treat data as a uInt32, whereas memcpy is treads it as bytes (chars), that's why you need to specify the number of bytes to copy.

Further more, memcpy is a C intrinsic function (meaning it tends to be inlined), whereas std::copy is part of the C++ standard library.
This is the problem I have with std::copy:

to copy in to the vector:
1
2
uInt32 foo = 1000;
std::copy(&foo, &foo + 1, std::back_inserter(this->buffer));


to copy from vector to uInt32 variable:
1
2
uInt32 data
std::copy(&buffer[outPos], &buffer[outPos] + sizeof(data), &data);


so how would I copy the unsigned int etc on a char and get the same thing back?
I don't see why you're using memcpy or std::copy to copy one int.

Assuming buffer is a char array, what's wrong with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
size_t inPos = 0;
Packet& Packet::operator << (uInt32 data)
{
    *(uInt32*)(&buffer[outPos]) = data;
    inPos += sizeof(data);
    return *this;
}

size_t outPos = 0;
Packet& Packet::operator >> (uInt32 & data)
{
    data = *(uInt32*)(&buffer[outPos]);
    outPos += sizeof(data);
    return *this;
}
Like I said though, I'm using a char vector, while that works it wouldn't really be inserting in to the vector, I would have to re-size each time, like I said in one of my questions is it better/faster to just create a big array and do operations on it?
I'm thinking std::copy would be better but in some cases it just messes up...

Out of interest, what do you mean by mess up??

so how would I copy the unsigned int etc on a char and get the same thing back?

Do you mean a char buffer? (copy an int into a char buffer??)

And...
- which platform are you currently working on?
- does your code need to work cross-platform?
- when you say "transfer it on the network", are you talking about sockets?

Andy
Last edited on
 
std::copy(&data[0], &data[0] + dataSize, std::back_inserter(buffer)


this for example doesn't do what I expect it to... because when I do this:

 
std::copy(&buffer[pos] , &buffer[pos] + dataSize, data);


data does not contain the same thing that I put in on the first function...
I mean copy it to a vector<char>

I am on windows 7.
It doesn't really need to work on other platforms.
Yes I am talking about network, lets not get into Endianess though, that is a different section lol.
Well, this

1
2
3
4
	vector<char> buffer;

	unsigned int foo = 1000;
	std::copy(&foo, &foo + 1, std::back_inserter(buffer));


is inserting one char into the vector, after which this

1
2
3
	unsigned int outPos = 0;
	unsigned int data = 0;
	std::copy(&buffer[outPos], &buffer[outPos] + sizeof(data), &data);


causes stack damage.

Whereas this, is ok

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void TestVec()
{
	vector<char> buffer;

	unsigned int foo = 1000;
	const char* p = reinterpret_cast<char*>(&foo);
	std::copy(p, p + sizeof(foo), std::back_inserter(buffer));

	unsigned int  outPos = 0;
	unsigned int bar = 0;
	std::copy(&buffer[outPos], &buffer[outPos] + sizeof(bar),
		  reinterpret_cast<char*>(&bar));

	cout << foo << " -> " << bar << endl;
}

int main()
{
	TestVec();

	return 0;
}


1000 -> 1000
Press any key to continue . . .

Andy
Last edited on
I swear I had tried this and it gave me errors or just spat out random numbers, it is working though... thanks man.
:-)

But kbw's solution looks like a good way to handle basic types (esp. as you don't care about endianness!)

Andy

PS Regarding

is it better/faster to just create a big array and do operations on it?

Depends on the cricumstance, I guess. But I did work on a bit of code where a large scratch buffer did speed things up a lot, but it was used a lot.

I assume you use reserve with your vector, too?
Last edited on
Yes I do use reverse too, kbw's solution is good I actually use that more often but only on raw data, containers and such tend to come back and bite you in the back when you mess with them in such a way.
Topic archived. No new replies allowed.