C++ STL vector for existing data
Asked Answered
N

4

13

Can I create an std::vector using my pre-existing data instead of it allocating new memory and copying the data?

To be clearer, if I have a memory area (either a c-array or part of another vector or whatever) and I want to provide vector-like access to it, can I create a vector and tell it to use this block of memory?

Ne answered 31/10, 2012 at 9:48 Comment(4)
How are you going to use that vector?Sinusoidal
Maybe it will be even better not to use vector or similar containers at all. Why do you want to put your data into a separate container?Floruit
It's important to know how you're going to use the vector. For example in Luchian's answer, the resulting vector won't be a vector<T>, it will be a vector<T,MyAllocator>. So if the reason you need a vector is to pass it to some function that expects a vector<T> then that won't help you. If you need the vector for some other purpose then maybe it will help you.Demars
@SteveJessop I am trying to make a 2d array class that behaves as similar to a vector as possible. Various methods will return a "row", which is really a portion of the internal "flat" vector. I guess if I need to I can just return iterators, but returning a vector seemed more logical to me.Ne
W
8

No, but you could write your own class that does this. Since this would be a fairly common need I wouldn't be surprised if someone else has done this already.

However the normal C++ way would be to write template code to operate on iterators. You can create iterators for any portion of a vector, or for any portion of a C array (and much else). So writing template code for iterators is probably what you should be doing.

Winther answered 31/10, 2012 at 9:52 Comment(5)
Can you explain this a little more? Do you mean to create a templated class with a vector-like interface that accepts iterators to it's constructor and uses them internally?Ne
Why should one try to reinvent the wheel when allocators can possibly do the job? The "new" vector may have 99% code in common with std::vector.Inapposite
@baruch: no, john is suggesting that instead of writing functions that accept a vector, you should write template functions that accept a pair of iterators. That way you can store your data in any container you like (e.g. vector, deque) or in a plain array. The problem of how to efficiently convert your plain array to a vector would disappear because you would no longer need a vector.Demars
@SteveJessop I have a class with an internal vector. Some methods, based on their input, need to return portions of this vector. How can I return a start and end iterator?Ne
@baruch I would return a pair of iterators from your method i.e. std::pair<std::vector<T>::iterator, std::vector<T>::iterator>. It's a bit clumsy but some STL methods (e.g. map::equal_range) do this.Winther
O
2

Since you can use a custom allocator when creating a vector, it is technically possible.

However, I wouldn't recommend it. I'd just create a vector with a fixed size (apparently you can get a hold of that) and then use std::copy.

Olatha answered 31/10, 2012 at 9:50 Comment(1)
What if the existing array has size n, and for whatever reason the vector asks the allocator for space of size n+1? I'm not saying that will definitely happen, but I'm pretty sure the standard allows vector to over-allocate by whatever margin it likes, and to use excess space at the end of its allocation for whatever it likes. You could probably write the allocator to notice anything unpleasant happening, and fall back to behaving like a normal allocator.Demars
S
1

Algorithms which iterate over a container accept a pair of iterators which define the input range. You can use the algorithm with iterators which point to a middle of a big container.

Examples:

std::vector<int> big_vector(100000);
// initialize it
//...
std::sort(big_vector.begin()+100, big_vector.begin()+200); // sort a subrange

int big_array[100000]; //c-style array
// initialize it
//...
std::sort(std::begin(big_array)+300, std::begin(big_array)+400); // sort a subrange
Sinusoidal answered 31/10, 2012 at 10:0 Comment(0)
M
1

From C++20 we have std::span which provides the exact same thing you are looking for. Take a look at https://en.cppreference.com/w/cpp/container/span.

Maricela answered 21/4, 2022 at 19:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.