3

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!

1
  • 1
    You might be looking for the proposed std::array_view, or string_view since this is of char. Commented Jul 1, 2015 at 21:16

2 Answers 2

6

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

Sign up to request clarification or add additional context in comments.

4 Comments

As a courtesy, here's the live stream of me answering this question (experiment)
@dyp I'd argue that there's no real value in using std::vector there then (the type will already be distinct due the custom allocator). But technically, that's a third option (depending on how narrowly you define std::vector<T> :))
@dyp Good luck passing that too void api2::foo(std::vector<char> const&); - that's why I said "I'd argue that there's no real value in using std::vector there". I think this is kind of the scenario the OP is facing. In fact, he should ask the library devs to fix the API to be less intrusive :)
@dyp I made this warning more explicit on your request.
1

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.

2 Comments

This is nice. It's important to realize that effectively you work on a vector of char* now (from a memory viewpoint) and this could impact performance very badly. This is reason for me not to upvote it here, because I think the context is all about maximizing performance, by eliminating allocation/copying.
@sehe It sounds right. Just thought this was worth noting, at least for objects.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.