STL векторный резерв () и копирование () - PullRequest
18 голосов
/ 15 июля 2009

Привет,

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

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.

Nat

/**
 * 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: 

Ответы [ 5 ]

32 голосов
/ 15 июля 2009

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

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 на самом деле не меняет размер вектора, а только его емкость.

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

24 голосов
/ 15 июля 2009

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

Когда вы 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>

19 голосов
/ 15 июля 2009

Почему бы и нет: vec2 = vec1;?

3 голосов
/ 24 января 2013

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

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

(см. http://www.sgi.com/tech/stl/Vector.html)

3 голосов
/ 15 июля 2009

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

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

Я считаю, что это то, что вам нужно.

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

...