LyingOnTheSky
LyingOnTheSky

Reputation: 2854

Making a vector out of array without allocation and memory copying

Roughly I have this API all over the place:

void func(const vector<int> &vint);

Which is badly designed, but I need to pass to it my int* without allocation\copy, as I found it to be a bottleneck. (executing memcpy concurrently on multiple threads won't copy faster)

I thought of writing a class like this:

template<typename T>
struct fake_vector {
    fake_vector(T *array, size_t array_length) {
        internal_vector.set_begin(array);
        internal_vector.set_end(array + array_length);
    }
    ~fake_vector() { // let's reset our internal vector so it won't try to deallocate our memory
        internal_vector.set_begin(nullptr);
        internal_vector.set_end(nullptr);
    }
    vector<T> &get() {
        return internal_vector;
    }

    vector<T> internal_vector;
};

And then use it like this:

fake_vector<int> my_fake_vector(vint,vint_length);
process(my_fake_vector.get());

But I don't know how to set begin\end of a vector. This question is open-ended for solution for this fake_vector last puzzle or a new less-hackish solution.

Upvotes: 1

Views: 184

Answers (1)

LyingOnTheSky
LyingOnTheSky

Reputation: 2854

You can by inheriting vector<T> and then tweaking with it's _M_impl._M_start and _M_impl._M_finish like this:

template<typename T>
struct fake_vector : vector<T> {
    fake_vector(T *array, size_t array_length) {
        vector<T>::_M_impl._M_start = array;
        vector<T>::_M_impl._M_finish = array + array_length;
    }
    ~fake_vector() { // let's reset our internal vector so it won't try to deallocate our memory
        vector<T>::_M_impl._M_start = nullptr;
        vector<T>::_M_impl._M_finish = nullptr;
    }
    vector<T> &get() {
        return *(vector<T>*)this;
    }
};

For example normal usage:

int x[3] = {1,2,3};
fake_vector<int> fake_x(x,3);
for (auto &p : fake_x)
    printf("%p = %d\n", &p, p);
for (int i = 0; i < 3; i++)
    printf("%p = %d\n", &x[i], x[i]);

Which outputs:

0x7ffeb42406e0 = 1
0x7ffeb42406e4 = 2
0x7ffeb42406e8 = 3
0x7ffeb42406e0 = 1
0x7ffeb42406e4 = 2
0x7ffeb42406e8 = 3

NOTE: If you are using libc++ (e.g. getting errors that _M_impl is not declared), then try replacing _M_impl._M_start with __begin_, and _M_impl._M_finish with __end_.

Upvotes: 2

Related Questions