c++ +memcpy alternative?

Started by
4 comments, last by StarikKalachnikov 18 years, 3 months ago
Hi, Just a short question, I read files the C++ way (fstreams and such) and have a function that returns a char* since ifstream.read uses char* as an out parameter. I then process the data with memcpy, e.g. memcpy(&header.id, buffer, sizeof(int)). Now I need to know if I'm on the right track, performance wise and C++ wise, like, is there a C++ way of getting the data out of char* buffer? I hope you can understand my question, :) Starik
Next time I give my advice, I'll buy some bubblegum so I won't your kick ass!
Advertisement
Performance-wise: ifstream already uses an internal buffer, so loading everything into your own buffer before processing it is awkward and redundant in many cases. Why not directly read the data into the object?

Design-wise: in my opinion, you should create friend function (member or external) to serialize objects. This will allow you to implement loading systems that go beyond the simple "copy the memory". Also, everything you might one day need is already implemented in a very performant way as part of the boost::serialize library.
If it's an alternative to memcpy() you're looking for, #include <algorithm> and use std::copy(). You could also try to have the stream directly place the data in its ultimate destination rather than in an intermediary buffer.

Or maybe I don't understand what you're trying to do.
"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
Well, I want to read the Milkshape format (.ms3d) and in the past I did it like this: (only relevant functions + pseudo code)

ReadModel(std::string aFilename){  ifstream file(aFileName.c_str(), ios::binary);  file.seekg(0, ios::end);  int length = file.tellg();  file.seekg(0, ios::beg);  char* buffer = new char[length];  file.read(buffer, length);  ms3dHeader header;  //milkshape header class with public members :(  memcpy(&header.id, buffer, sizeof(int));  buffer += sizeof(int);  memcpy(&header.version, buffer, sizeof(char) * 10);  buffer += sizeof(char) * 10;  int vertexCount = 0;  memcpy(&vertexCount, buffer, sizeof(word));  buffer += sizeof(word);  //and so on... }


I don't have access to my code right now, so there are probably errors in it, and maybe the code style is even worse, which is what I'm trying to figure out.

But what I understand right now is that I need to modify my classes, add a function with a parameter (stream)(probably make an abstract base class for consistency), and read the appriate data present?
Do you have any examples I can look at?

Thanks so far!
Next time I give my advice, I'll buy some bubblegum so I won't your kick ass!
Just as ToohrVyk has pointed out, you are needlessly loading the entire file into an intermediate buffer. You can instead directly use the istream interface to read the data:

struct MilkshapeHeader {  int id;  char version[10];  short vertexCount;    friend std::istream &operator >>(std::istream &i, MilkshapeHeader &header) {    i.read(reinterpret_cast<char *>(&header.id), sizeof(header.id));    i.read(reinterpret_cast<char *>(&header.version), sizeof(header.version));    i.read(reinterpret_cast<char *>(&header.vertexCount), sizeof(header.vertexCount));    return i;  }};int main() {  MilkshapeHeader header;  std::ifstream("test.milkshapemodel", std::ios::binary) >> header;}


However, performance-wise, the iostream library is not so great for binary data because of the inefficient internal buffering approach. Of course this varies with the implementation you use, but any valid implementation of the standard libraries is required to provide the entire chain down to the std::streambuf.

-Markus-
Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
Your answer is giving me alot to think about and I will try make something similar like the code you posted.

Thanks all!

Next time I give my advice, I'll buy some bubblegum so I won't your kick ass!

This topic is closed to new replies.

Advertisement