Lucidus
Lucidus

Reputation: 33

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!

Upvotes: 3

Views: 1289

Answers (2)

sehe
sehe

Reputation: 393583

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

Upvotes: 6

Miki
Miki

Reputation: 41775

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.

Upvotes: 1

Related Questions