Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to construct a std::vector or a boost::array from a C array without copying?

Given a pointer to an array of char, is it possible to construct a std::vector or boost::array from it, and avoiding memory copying?

Thanks in advance!

like image 415
Lucidus Avatar asked Feb 18 '26 23:02

Lucidus


2 Answers

Because vectors own their own allocators and storage alike, there is no way (for non primitive elements construction from move_iterators could help a bit).

So assuming the goal is to get a true std::vector<char>& for the existing storage, you'll never succeed, not even with custom allocators¹.


If you want a string, you can use boost::string_ref (in utility/string_ref.hpp).

Otherwise, you could use a 1-dimensional multi_array_ref (from Boost Multi Array)

1. Using string_ref

This is definitely easiest:

Live On Coliru

#include <boost/utility/string_ref.hpp>
#include <iostream>

using boost::string_ref;

int main() {
    char some_arr[] = "hello world";

    string_ref no_copy(some_arr);

    std::cout << no_copy;
}

2. multi_array_ref

This is more versatile, and works "better" if you are not geared towards a string interface.

Live On Coliru

#include <boost/multi_array/multi_array_ref.hpp>
#include <iostream>

using ref = boost::multi_array_ref<char, 1>;
using boost::extents;

int main() {
    char some_arr[] = "hello world";

    ref no_copy(some_arr, extents[sizeof(some_arr)]);

    std::cout.write(no_copy.data(), no_copy.num_elements());
}

Both examples print

hello world

¹ specializing std::allocator<char> is too evil to consider and probably outright prohibited by the standard

like image 181
sehe Avatar answered Feb 20 '26 13:02

sehe


An alternative without using boost would be std::reference_wrapper

#include <vector>
#include <iostream>
#include <functional>

using namespace std;

struct S
{
    S() : val(0) {}
    S(int val_) : val(val_) {}
    S(const S& other) : val(other.val) {
        cout << "copy" << endl;
    }

    int val;
};


int main()
{
    char a[] = "Hello";
    vector<reference_wrapper<char>> v(a, a+5);

    S vS[] = {S(1), S(2), S(3)};

    vector<S> v_copy(vS, vS + 3);
    vector<reference_wrapper<S>> v_nocopy(vS, vS+3);
}

Using struct Syou can see that objects are not copied to the vector. So this should work well also for char.

like image 42
Miki Avatar answered Feb 20 '26 12:02

Miki



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!