简体   繁体   中英

Build a vector as a subset of another one without copying

Let v be a vector. I would like w to be a subset of v between the indices from and to . I could just do

std::vector<T> w(v.begin() + from, v.begin() + to);

However, I do not intend to use v in the future. As such, I don't need to copy the data between from and to . I would need to create a vector who points to v.begin() + from and is of length to - from . The rest of the memory used by v should be freed. Note that I am fine if it is v being redefined (I can just swap to w afterward if I want to anyway).

Is it possible to do that?

If you want to use a vector , there is no way to avoid copying. If you want to be sure unused memory is released, you could do it like this :

std::vector<T> w(v.begin() + from, v.begin() + to);
std::vector<T>().swap(v);

This should do the trick with vector.

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> v{ 11, 22, 33, 44, 55, 66, 77, 88, 99 };
    constexpr size_t from = 3;
    constexpr size_t to = 7;

    if(to < v.size() - 1)
        v.erase(v.begin() + to, v.end());

    if(from > 0)
        v.erase(v.begin(), v.begin() + from - 1);

    v.shrink_to_fit();

    for(auto i : v)
        cout << i << ' ';
    cout << endl;
}

You should probably use a std::deque, and pop all the elements from begin() to begin() +front, and from end() - to to end(). That will free the unusded memory minus a tiny chunk from the front of the first bucket and the end of the last bucket. std::deque is very performant, since it stores its contents in buckets of arrays. It is not just as performant as vector, but it's in practice probably good enough since its just 1 extra level of indirection. Roughly this is the difference:

  • std::vector [i] -> return buffer[i]
  • std::deque[i] -> buckets[i] -> return bucket[i];

Reference: https://en.cppreference.com/w/cpp/container/deque

It depends on how much you grow and shrink your vector, but deque shrinks and grows whithout copying any elements ever, its just bucket allocation/deallocation. So it can be much more performant than vector in some scenarios.

Should be available soon. In the meantime, your options are:

  1. Use std::string<T> rather than vector , and, consequently, std::string_view .

  2. Craft your own view class. Say,

     template<class Iterator> class view { Iterator b, e; public: view(Iterator b, Iterator e): b(b), e(e) {} auto &operator[](std::size_t i) { return *(b[i]); } auto const &operator[](std::size_t i) const { return *(b[i]); } auto begin() const { return b; } auto end() const { return e; } auto size() const { return e - b; } }; 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM