How to avoid extra copy of data buffer to string?

2156 views c++
4

The following is skeleton code for saving multiple pieces of data to myqueue. Each chunk of data can be large (say a few MB or more). I have two questions:

  • By creating a string from a buf *, does it involving copying buf to new location? is there any performance concern?

  • In the dequeue function, I am returning string as a reference, is this the right way to avoid creating new string?

Thanks.

int main() {
   std::queue<std::string> myqueue;
   ... 
   // receive large number
   // data, and enqueue to myqueue
}

void enqueue()
{
   char* buf = (char*)malloc(count);
   myqueue.push(std::string(buf));
   free(buf);
}

std::string& dequeue()
{
   std::string& item = myqueue.front();
   myqueue.pop()
   return item;
}

answered question

2 Answers

5

By creating a string from a buf *, does it involving copying buf to new location? is there any performance concern?

Yes. It could be. Unless the pattern of usage is clear, it's hard to say whether you need to be concerned.

In the dequeue function, I am returning string as a reference, is this the right way to avoid creating new string?

No, it is not. You are getting a reference to an object that is not alive when the function returns. Accessing the object through the reference will cause undefined behavior. Be safe and return an object by value.

std::string dequeue()
{
   std::string item = myqueue.front();
   myqueue.pop();
   return item;
}

posted this
0

In

void enqueue()
{
   char* buf = (char*)malloc(count);
   myqueue.push(std::string(buf));
   free(buf);
}

the std::string(buf) can't take ownership of buf so you are going to have to allocate more memory, copy buf into that memory and then put it into the queue. We can make this better by starting with a std::string to begin with. That would give you something like

void enqueue()
{
   myqueue.push(std::string(count, '\0'));
}

or if you need to load data into the string

void enqueue()
{
    std::string buf(count, '\0');
    load_data(buf.data());
    myqueue.push(std::move(buf));
}

In

std::string& dequeue()
{
   std::string& item = std::move(myqueue.front());
   myqueue.pop();
   return item;
}

you are returning a reference to a local object. That will lead to undefined behavior because as soon as the function ends the local string is destroyed and you are left with a dangling reference. TO prevent that you can just return the string by value like

std::string dequeue()
{
   std::string item = myqueue.front();
   myqueue.pop();
   return item;
}

posted this

Have an answer?

JD

Please login first before posting an answer.