Reputation: 18239
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?
Upvotes: 4
Views: 2575
Reputation: 476
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:
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.
Upvotes: 0
Reputation: 6125
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);
Upvotes: 2
Reputation: 711
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;
}
Upvotes: 1
Reputation: 11950
Should be available soon. In the meantime, your options are:
Use std::string<T>
rather than vector
, and, consequently, std::string_view
.
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; }
};
Upvotes: 0