Векторный резерв STL() и копия()

Привет,

Я пытаюсь выполнить копию из одного вектора (vec1) в другой вектор (vec2), используя следующие две сокращенные строки кода (следующее тестовое приложение):

vec2.reserve( vec1.size() );
copy(vec1.begin(), vec1.end(), vec2.begin());

В то время как вызов vec2 задает емкость вектора vec2, копирование данных в vec2, похоже, не заполняет значения от vec1 до vec2.

Замена функции copy() вызовами push_back() работает как ожидалось.

Что мне здесь не хватает?

Спасибо за вашу помощь. Затем следует тестовая программа vectest.cpp, за которой следует итоговый результат.

Компилятор: gcc 3.4.4 на cygwin.

Нат

/**
 * vectest.cpp
 */

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> vec1;
    vector<int> vec2;

    vec1.push_back(1);
    vec1.push_back(2);
    vec1.push_back(3);
    vec1.push_back(4);
    vec1.push_back(5);
    vec1.push_back(6);
    vec1.push_back(7);

    vec2.reserve( vec1.size() );
    copy(vec1.begin(), vec1.end(), vec2.begin());

    cout << "vec1.size()     = " << vec1.size() << endl;
    cout << "vec1.capacity() = " << vec1.capacity() << endl;

    cout << "vec1: ";
    for( vector<int>::const_iterator iter = vec1.begin(); iter < vec1.end(); ++iter ) {
        cout << *iter << " ";
    }
    cout << endl;

    cout << "vec2.size()     = " << vec2.size() << endl;
    cout << "vec2.capacity() = " << vec2.capacity() << endl;
    cout << "vec2: ";
    for( vector<int>::const_iterator iter = vec2.begin(); iter < vec2.end(); ++iter ) {
        cout << *iter << endl;
    }

    cout << endl;
}

выход:

vec1.size()     = 7
vec1.capacity() = 8
vec1: 1 2 3 4 5 6 7 
vec2.size()     = 0
vec2.capacity() = 7
vec2: 

Ответы

Ответ 1

Как отмечалось в других ответах и ​​комментариях, для этого вам нужно просто использовать встроенные в векторные функции. Но:

Когда вы reserve() элементы, вектор выделит достаточно места для (по крайней мере?), что многие элементы. Элементы не существуют в векторе, но память готова к использованию. Это, возможно, ускорит push_back(), поскольку память уже выделена.

Когда вы resize() вектор, он выделит достаточно места для этих элементов, , но также добавит их в вектор.

Итак, если вы измените размер вектора на 100, вы можете получить доступ к элементам 0 - 99, но если вы зарезервируете 100 элементов, они еще не вставлены, просто готовы к использованию.

Что вы хотите, это примерно так:

vec2.reserve( vec1.size() );
copy(vec1.begin(), vec1.end(), std::back_inserter(vec2));

std::back_inserter определяется в <iterator>

Ответ 2

Если векторы одного типа, используйте построение копирования или назначение копии:

vec2(vec1);
vec2 = vec1;

Если векторы не являются точными (возможно, другой распределитель или что-то еще, или vec1 - это deque), то вы действительно хотите - это конструктор на основе диапазона или назначение на основе диапазона:

vec2(vec1.begin(), vec1.end()); // range-based constructor

vec2.assign(vec1.begin(), vec1.end()); // range-based assignment

Если вы настаиваете на том, чтобы сделать это с помощью std::copy, правильный метод:

copy(vec1.begin(), vec1.end(), back_inserter(vec2));

Так как резервирование пространства не делает его назначаемым. copy работает, назначая каждому элементу новое значение. Таким образом, vec2.size() должен быть как минимум равным vec1.size() в вашем случае. Вызов reserve фактически не меняет размер вектора, а только его емкость.

В книге "Эффективный STL" Скотт Майерс утверждает, что почти все виды использования std:: copy для вставки должны быть заменены функциями-членами на основе диапазонов. Я предлагаю вам получить копию, это отличная ссылка!

Ответ 3

Почему не: vec2 = vec1;?

Ответ 4

Изменить резерв для изменения размера():

vec2.resize(vec1.size(), '\0');
copy(vec1.begin(), vec1.end(), vec2.begin());

Я считаю, что это исправление, в котором вы нуждаетесь.

Я не могу дать вам очень хорошее описание разницы, но в основном reserve() гарантирует, что у вас достаточно места, а resize() фактически вставляет что-то там.

Ответ 5

На мой взгляд, самый простой способ - использовать метод std::vector::insert:

v2.insert(v2.end(), v1.begin(), v1.end());

(см. std::vector :: insert)