Создайте вектор как подмножество другого без копирования - PullRequest
0 голосов
/ 13 декабря 2018

Пусть v будет вектором.Я бы хотел, чтобы w было подмножеством v между индексами from и to.Я мог бы просто сделать

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

Однако я не собираюсь использовать v в будущем.Поэтому мне не нужно копировать данные между from и to.Мне нужно создать вектор, который указывает на v.begin() + from и имеет длину to - from.Остальная часть памяти, используемая v, должна быть освобождена.Обратите внимание, что у меня все хорошо, если переопределить v (я могу просто поменять на w впоследствии, если захочу).

Возможно ли это сделать?

Ответы [ 4 ]

0 голосов
/ 13 декабря 2018

Это должно сработать с вектором.

#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;
}
0 голосов
/ 13 декабря 2018

Если вы хотите использовать vector, нет способа избежать копирования.Если вы хотите убедиться, что неиспользуемая память освобождается, вы можете сделать это следующим образом:

std::vector<T> w(v.begin() + from, v.begin() + to);
std::vector<T>().swap(v);
0 голосов
/ 13 декабря 2018

Должно быть доступно в ближайшее время. В то же время, ваши варианты:

  1. Используйте std::string<T> вместо vector, и, следовательно, std::string_view.

  2. Создайте свой собственный класс представления.Скажем,

    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; }
    };
    
0 голосов
/ 13 декабря 2018

Вам, вероятно, следует использовать std :: deque и вытолкнуть все элементы из begin () в begin () + front, а из end () - в end ().Это освободит неиспользованную память минус крошечный кусок с передней части первого сегмента и с конца последнего сегмента.std :: deque очень производительный, так как он хранит свое содержимое в массивах массивов.Он не так эффективен, как вектор, но на практике он, вероятно, достаточно хорош, поскольку имеет всего 1 дополнительный уровень косвенности.Примерно в этом разница:

  • std :: vector [i] -> буфер возврата [i]
  • std :: deque [i] -> buckets [i] ->return bucket [i];

Ссылка: https://en.cppreference.com/w/cpp/container/deque

Это зависит от того, насколько вы растете и сжимаете свой вектор, но deque сжимается и растет без копирования каких-либо элементов, егопросто распределение / освобождение ведра.Так что в некоторых сценариях он может быть намного более производительным, чем вектор.

...