Reputation: 33
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
Reputation: 393583
Because vectors own their own allocators and storage alike, there is no way (for non primitive elements construction from move_iterator
s 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)
This is definitely easiest:
#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;
}
multi_array_ref
This is more versatile, and works "better" if you are not geared towards a string interface.
#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
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 S
you can see that objects are not copied to the vector. So this should work well also for char
.
Upvotes: 1