mans
mans

Reputation: 18168

How to create a vector around a buffer?

I have a code which is similar to the following:

 myLibFunc(std::vector<char > &data)
 {
     // dosomthing with data
 }
 myFunc(char *buffer,int bufferSize)
 {
       std::vector<char > mydata(buffer,buffer+bufferSize);
       myLibFunc(mydata);
 }

The code works, but the vector allocates memory for itself and not using a memory that is already available.

How can I change the code in such a way that the vector uses the memory that already available and not allocating an extra memory?

Note that I can not change the signature of functions.

Update

I have two functions:
In one of them, I receive a buffer and I need to manipulate the memory and pass it to the next function as a vector. The function that I am trying to implement is part of an interface so I can not change it. Another function is a library that I need to call, so I can not change the signature of functions.
The problem is that the above code allocates new memory and copies the data from the buffer to it which is not optimal.

Upvotes: 4

Views: 1208

Answers (2)

Justin Finnerty
Justin Finnerty

Reputation: 329

std::vector is designed to exclusively own the data it holds so doing the memory copy is the only safe way for std::vector to work. That leaves only unsafe hacks. If we can assume the function does not change the vector size, you can abuse std::vector. In my compiler (tested on g++4.8 and cpp.sh) std::vector is implemented as three pointers (to begin data, end used data and end alloc) therefore I can abuse the vector as:

#include <vector>
#include <iostream>

void myLibFunc( std::vector< char > & a )
{
    for( char c : a )
    {
        std::cout << '[' << c << ']';
    }
    a[0] = 'B'
    std::cout << '\n';
}

void myFunc(char *buffer,int bufferSize)
{
   std::vector<char > mydata;
   // cast to alterable pointers, cast should also keep 
   // mydata in scope until after the last assignment.
   char ** abuser = (char**)&mydata;
   // save old values and substitute new values
   char *tmp0 = abuser[0];
   abuser[0] = buffer;
   char *tmp1 = abuser[1];
   abuser[1] = buffer+bufferSize;
   char *tmp2 = abuser[2];
   abuser[2] = buffer+bufferSize;
   myLibFunc(mydata);
   // return old values to avoid crash when mydata goes out of scope.
   abuser[0] = tmp0;
   abuser[1] = tmp1;
   abuser[2] = tmp2;
}

int main()
{
    char p[] = "Hello World";
    myFunc( &p[0] + 2, 5 );
    std::cout << p << '\n';
    return 0;
}

Note this abuse is likely to be non-portable and lead to unexplained crashes.

Upvotes: 1

OutOfBound
OutOfBound

Reputation: 2004

If you can not change the signature of your function it is not possible without the copy.

But a better way is to think about your interface. If you build myLibFunc on random access iterators, your problem is solved:

template <class CharRandomAccessIterator>
 myLibFunc(CharRandomAccessIterator& begin, CharRandomAccessIterator& end )
 {
     // dosomthing with data
     size = end - begin;
     begin[xyz]; // access elements
 }
 myFunc(char *buffer,int bufferSize)
 {
       std::vector<char > mydata(buffer,buffer+bufferSize);
       myLibFunc(mydata.begin(), mydata.end()); // This will work
       myLibFunc(buffer, buffer+size); // This will work too
 }

Upvotes: 0

Related Questions