How can I construct a std :: vector or boost :: array from a C array without copying?
Since vectors have their own allocators and storage, there is no way (for constructing non-primitive elements from move_iterator
, a bit can help).
So, assuming this will be true for the existing store std::vector<char>&
, you will never succeed, even with custom allocators.
If you need a string, you can use boost::string_ref
(in utility/string_ref.hpp
).
Otherwise you can use 1-dimensional multi_array_ref
(from Boost Multi Array)
1. Using string_ref
This is definitely the 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;
}
2. multi_array_ref
This is more versatile and works "better" if you are not string-oriented.
#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 in std::allocator<char>
, too vicious to consider and possibly outright forbidden by the standard
source to share
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);
}
By using struct S
you can see that objects are not copied to vector. So this should work well for char
.
source to share