Лучший способ добавить вектор к вектору
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();
Ответы
Ответ 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
и перебирают их, когда вам нужно читать их данные.