Подтвердить что ты не робот

Лучший способ добавить вектор к вектору

std::vector<int> a;
std::vector<int> b;
std::vector<int> c;

Я хотел бы объединить эти три вектора, добавив b и c элементы в a. Каков наилучший способ сделать это и почему?


1) Используя vector::insert:

a.reserve(a.size() + b.size() + c.size());
a.insert(a.end(), b.begin(), b.end());
a.insert(a.end(), c.begin(), c.end());
b.clear();
c.clear();

2) Используя std::copy:

a.reserve(a.size() + b.size() + c.size());
std::copy(b.begin(), b.end(), std::inserter(a, a.end()));
std::copy(c.begin(), c.end(), std::inserter(a, a.end()));
b.clear();
c.clear();

3) Используя std::move (из C++11):

a.reserve(a.size() + b.size() + c.size());
std::move(b.begin(), b.end(), std::inserter(a, a.end()));
std::move(c.begin(), c.end(), std::inserter(a, a.end()));
b.clear();
c.clear();
4b9b3361

Ответ 1

На мой взгляд, ваше первое решение - лучший способ пойти.

vector<>::insert предназначен для добавления элемента, чтобы он был наиболее подходящим решением.

Вы можете называть reserve для вектора назначения, чтобы зарезервировать некоторое пространство, но если вы не добавите много вектора вместе, скорее всего, это не принесет больших преимуществ: vector<>::insert знать, сколько элементов будет добавлено, вы будете избегайте только одного вызова reserve.

Примечание. Если они были vector более сложного типа (т.е. пользовательский класс или даже std::string), то использование std::move может обеспечить вам хороший прирост производительности, поскольку это позволит избежать создания экземпляра-копии, Однако для вектора int он не даст вам никаких преимуществ.

Примечание 2: Следует отметить, что использование std::move приведет к непригодности содержимого вашего источника vector.

Ответ 2

Предполагая, что вы хотите скопировать и не двигаться, это будет лучший способ:

a.reserve(a.size()+b.size()+c.size()); // Reserve space first
a.insert(a.end(),b.begin(),b.end());
a.insert(a.end(),c.begin(),c.end());

Если вы хотите переместить:

a.reserve(a.size()+b.size()+c.size()); // Reserve space first
a.insert(a.end(),std::make_move_iterator(b.begin()),
         std::make_move_iterator(b.end()));
a.insert(a.end(),std::make_move_iterator(c.begin()),
         std::make_move_iterator(c.end()));
b.swap(std::vector<int>()); // Clear and deallocate space
c.swap(std::vector<int>()); // Clear and deallocate space

Обновление. Вы отредактировали свой вопрос несколько раз, сделав его частью движущейся цели. Ваш первый вариант теперь очень похож на мое первое предложение.

Ответ 3

Первый - лучший выбор, потому что insert может определить, сколько элементов он добавляет и изменяет размер вектора до его начала, прежде чем он начнет копирование. У других нет такой информации, поэтому после некоторого копирования может закончиться изменение размера, которое будет медленнее, чем изменение размера в начале, или изменение размера более одного раза.

Однако, поскольку подсказки @michaelgoldshteyn, так как вы собираетесь делать две вставки, вы также можете изменить размер массива с конечным размером, сохраняя при этом один размер.

Ответ 4

Если вы действительно хотите добавить данные b и c в вектор a, вам нужно сделать вставку (которая на самом деле является вашей 1.):

a.reserve( a.size() + b.size() + c.size() ); // preallocate memory (see why)
a.insert( a.end(), b.begin(), b.end() );
a.insert( a.end(), c.begin(), c.end() );

В зависимости от компилятора std::copy (ваш 2.) обычно должен быть как можно быстрее.

Так как a std::vector всегда должно быть смежным в памяти, вы не можете просто перемещаться (как определено в С++ 11), и если вы знаете размер конца , вам нужно зарезервировать свой вектор (это позволит избежать ненужных перераспределений вашего вектора). Но если вы действительно беспокоитесь о производительности, пусть это три слова std::vector и перебирают их, когда вам нужно читать их данные.