Хороший способ добавить вектор к себе

Я хочу дублировать содержимое вектора и хочу, чтобы они были добавлены в конце исходного вектора i.e. v[i]=v[i+n] for i=0,2,...,n-1

Я ищу хороший способ сделать это, а не с циклом. Я видел std::vector::insert, но итеративная версия запрещает итератору *this (то есть поведение undefined).

Я также пробовал std::copy следующим образом (но это привело к ошибке сегментации):

copy( xx.begin(), xx.end(), xx.end());

Ответ 1

Ого. Так много ответов, которые близки, ни одного со всеми правильными деталями. Вам нужны как resize (или reserve), так и copy_n, а также запоминание исходного размера.

auto old_count = xx.size();
xx.resize(2 * old_count);
std::copy_n(xx.begin(), old_count, xx.begin() + old_count);

или

auto old_count = xx.size();
xx.reserve(2 * old_count);
std::copy_n(xx.begin(), old_count, std::back_inserter(xx));

При использовании reserve требуется copy_n, потому что итератор end() указывает один элемент за конец... что означает, что он также не является "до точки вставки" первой вставки и становится недействительным.


23.3.6.5 [vector.modifiers] promises, что для insert и push_back:

Примечания: вызывает перераспределение, если новый размер больше старой. Если перераспределение не происходит, все итераторы и ссылки до точки вставки остаются в силе. Если исключение генерируется иначе, чем конструктор копирования, переместите конструктор, оператор присваивания или оператор назначения перемещения из T или любая операция InputIterator не вызывает никаких эффектов. Если исключение выбрасывается конструктором перемещения не-CopyInsertable T, то параметры не заданы.

Ответ 2

Я бы сделал это следующим образом:

#include <algorithm>
#include <vector>
#include <utility>

int main(int argc, char* argv[])
{
    std::vector<int> v1 = { 1, 2, 3, 4, 5 };

    {
        std::vector<int> v2(v1.begin(), v1.end());
        std::copy(v1.begin(), v1.end(), std::back_inserter(v2));
        std::swap(v1, v2);
    }

    return 0;
}

EDIT: я добавил немного более эффективную версию.

#include <algorithm>
#include <vector>
#include <utility>

int main(int argc, char* argv[])
{
    std::vector<int> v1 = { 1, 2, 3, 4, 5 };

    {
        typedef std::move_iterator<decltype(v1)::iterator> VecMoveIter;
        std::vector<int> v2(v1);
        std::copy(VecMoveIter(v1.begin()), VecMoveIter(v1.end()), std::back_inserter(v2));
        v1 = std::move(v2);
    }

    return 0;
}

Ответ 3

Для добавления нескольких слотов дубликатов.

    int main() {
        std::vector<int> V;
        V.push_back(1);
        V.push_back(2);

        int oldSize = V.size();
        int newSize = oldSize;
        int nDupSlot = 4;

        V.resize(nDupSlot * oldSize);
        for(int i=0; i<(nDupSlot-1); ++i) {
            std::copy_n(V.begin(), oldSize, V.begin() + newSize);       
            newSize = newSize + oldSize;
         }

        for(int i =0; i<V.size(); ++i) {
            std::cout<<V[i];
            }

        return 0;
    }

Вывод:

12121212

Ответ 4

Это может быть не самый эффективный способ, но он прост:

std::vector<int> toAppend(xx);
xx.insert(xx.end(), toAppend.begin(), toAppend.end();