3

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.

Milan
  • 1,743
  • 2
  • 13
  • 36
mans
  • 17,104
  • 45
  • 172
  • 321
  • 2
    First of all, you create a vector of C-style *strings*, not a vector of characters. As for your problem, it seems like you want a [`std::string_view`](http://en.cppreference.com/w/cpp/string/basic_string_view). It's easy to create a `string_view`-like wrapper if you don't have `std::string_view` yet. – Some programmer dude Dec 13 '17 at 11:56
  • Then you can't use a `vector`, since you'd need to give it a different allocator type, and that's a template argument, which thus changes signatures. – underscore_d Dec 13 '17 at 11:56
  • 2
    you cant. containers manage their own memory by design. You want a view rather than a container – 463035818_is_not_an_ai Dec 13 '17 at 11:56
  • 1
    Short answer: you don't. You create your vector and if you need access to the raw pointer then you can do `data()` – UKMonkey Dec 13 '17 at 11:57
  • As currently written, the question seems like an exact duplicate of [Looking for C++ STL-like vector class but using stack storage](https://stackoverflow.com/questions/354442/looking-for-c-stl-like-vector-class-but-using-stack-storage), particularly the first hypothetical piece of code – underscore_d Dec 13 '17 at 12:03
  • The only way a vector will allocate memory is if your code does something which resizes or reserves a new capacity. If you are doing such operations, it's not reasonable to expect it to not allocate memory. – Peter Dec 13 '17 at 12:03
  • @Someprogrammerdude Update code to fix the issue. Is there any std:;vector_view or something such as this? – mans Dec 13 '17 at 12:11
  • @underscore_d It is not as that function asked for a container that allocate on stack, here I want a vector that doesn't allocate memory and don't manage memory by itself, but wrap around a memory which is already allocated. – mans Dec 13 '17 at 12:15
  • By default there is no such thing for vector. What you can do is to create a custom allocator to manage your memory. – Logman Dec 13 '17 at 12:22
  • @Logman Any information about how I can do this? – mans Dec 13 '17 at 12:23
  • Don't go the way with the custom allocator. It gets too messy. – OutOfBound Dec 13 '17 at 12:27
  • As @OutOfBound said it's difficult path but I think it's the only way. Try read [this](http://en.cppreference.com/w/cpp/memory/allocator). – Logman Dec 13 '17 at 12:31
  • 2
    @Logman the custom allocator changes the type. `std::vector` is incompatible with `std::vector`, at which point you may as well use `string_view` – Caleth Dec 13 '17 at 12:32
  • Is memory really that critical in this program? It seems kind of overkill to try to achieve such a tiny optimization... you will have to allocate memory anyway, since a vector contains overhead that makes it larger than a simple buffer for the same data. – Matthieu.V Dec 13 '17 at 12:37
  • @Matthieu.V The buffer size is very big, it is around 500Mbyte. and during my process I need to create different vectors from different part of the buffer to be able to process them via myLibFunc. – mans Dec 13 '17 at 12:52
  • @WernerHenze I am getting it as parameter to my function. – mans Dec 13 '17 at 12:58
  • @Caleth I was thinking to combine it with std::swap. I expect library will not modify container itself it will modify only elements, but if it's not true the whole idea is not valid. – Logman Dec 13 '17 at 13:11
  • If you want horrendous UB code, [here](https://gist.github.com/YashasSamaga/88a1368dbf26b0ffd051764b57f630fa) it is. It works on my PC but it needn't on yours, HAHA. – Yashas Dec 13 '17 at 15:03
  • @JustinFinnerty instead you prefer to assume that OP is not qualified to ask proper question. – Logman Dec 13 '17 at 18:28

2 Answers2

1

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.

Justin Finnerty
  • 329
  • 1
  • 7
  • Here's my version too: [this](https://gist.github.com/YashasSamaga/88a1368dbf26b0ffd051764b57f630fa) (no offense to those who take this as brutal treatment of C++) – Yashas Dec 13 '17 at 15:02
0

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
 }
OutOfBound
  • 1,914
  • 14
  • 31