2010-03-11 4 views
14

У меня есть вектор, объявленный как глобальная переменная, который мне нужно для повторного использования. Например, я читаю несколько файлов данных, анализируя данные для создания объектов, которые затем хранятся в векторе.Повторное использование вектора в C++

vector<Object> objVector(100); 

void main() 
{ 
while(THERE_ARE_MORE_FILES_TO_READ) 
{ 
    // Pseudocode 
    ReadFile(); 
    ParseFileIntoVector(); 
    ProcessObjectsInVector(); 
    /* Here I want to 'reset' the vector to 100 empty objects again */ 

} 

}

Могу ли я сбросить вектор, чтобы быть "вектор objVector (100)", так как он был первоначально выделен на стеке? Если я делаю «objVector.clear()», он удаляет все 100 объектов, и у меня будет вектор с размером 0. Мне нужно, чтобы он был размером 100 в начале каждого цикла.

+0

Вам нужно сохранить объекты или вы хотите сбросить их до состояния по умолчанию? – Macke

+1

В вашем примере объект objVector статически выделен. Он не выделяется в стеке. – Alan

+3

Неверный тип возврата вашей основной функции. В C и C++ main всегда должен возвращать int (но если вы ничего не вернете, C++ и C99 автоматически вернут 0). – Tronic

ответ

4
vector<Object> objVector(100); 

int main() 
{ 
while(THERE_ARE_MORE_FILES_TO_READ) 
{ 
    // Pseudocode 
    ReadFile(); 
    ParseFileIntoVector(); 
    ProcessObjectsInVector(); 
    /* Here I want to 'reset' the vector to 100 empty objects again */ 
    objVector.clear(); 
    objVector.resize(100); 

} 
} 
+0

Это сделало. Благодаря! – Blade3

+2

Ну, я все еще думаю, что swap() - это рекомендуемый способ выполнения такого рода работы. См. Пункт 17 «Эффективный STL»: используйте «трюк свопа» для обрезки избыточной емкости. сделать четкое, а затем изменить размер на самом деле медленнее - он имеет дополнительные операции выделения памяти, чем своп() –

+2

Обрезка избыточной емкости чаще всего нежелательна (поэтому stdlib этого не делает). Возникновение производительности вызвано частыми выделениями. Выгода от производительности, вызванная повторным использованием вектора, также будет полностью потеряна. – Tronic

2

Вызов изменить размер в начале или в конце цикла: http://www.cplusplus.com/reference/stl/vector/resize/

Это должно делать то, что вы хотите. Однако я бы рекомендовал использовать функции push и pop. Он более эффективен в пространстве и как предполагается использовать вектор. Вектор будет расширяться и уменьшаться по мере необходимости, когда вы нажимаете (добавляете) и извлекаете (удаляете) предметы из него. Таким образом, вам не нужно беспокоиться о размере или содержимом вектора. Он просто становится очереди обработки.

1

Следующий код должен сделать трюк.

vector<Object> temp(100); 
objVector.swap(temp); 
+0

Это не очень помогает, так как вы просто отбрасываете другой вектор, но вы все равно отказываетесь от него. –

+0

@Let_Me_Be: Это отбрасывает то, что у вас уже было, заменив его на 100 построенных по умолчанию объектов - то, о чем попросил ОП. – UncleBens

+0

@Let_Me_Be: Я действительно не совсем понимаю ваш комментарий. Не могли бы вы прояснить ситуацию? –

6
objVector.clear(); 
objVector.resize(100); 

Однако, это, вероятно, не рекомендуется использование вектора. Вы уверены, что не должны использовать push_back с вектором, который изначально пуст? Как вы можете быть уверены, что каждый файл содержит ровно 100 объектов, не более того, как это видно из вашего вопроса?

Вектор, вероятно, также не должен быть глобальным. Лучше все обойти. Когда вы видите кучу функций, называемых без параметров, довольно сложно, если не невозможно, следить за тем, что происходит (потому что все остальные, кроме вас, включая вас, когда вы вернетесь к этому коду через несколько месяцев, будут иметь не знаю, что эти функции используют для ввода и что такое вывод).

0

Позвоните objVector.clear(), чтобы удалить предыдущие точки данных, а затем objVector.resize(100), чтобы изменить его размер до нужного размера.

Обратите внимание, что это будет выделение 1 экземпляра Object с использованием конструктора по умолчанию, а затем 100 копий Object с использованием конструктора копирования, который может быть или не быть тем, что вы действительно хотите. Необязательно, если Object является типом указателя, вы можете использовать objVector.resize(100, NULL), чтобы избежать возможных нежелательных распределений.

+0

Никакое нежелательное распределение не будет иметь место, если 'Object' является типом указателя, передача' NULL' 'to resize' полностью избыточна, так как то же самое произойдет без него. –

+0

Кроме того, утверждение о конструкторе копирования неверно. Конструктор по умолчанию будет вызываться каждый раз, то есть 100 раз. –

+0

@ Konrad, вы ошибаетесь во второй точке. Значение по умолчанию можно назвать 100 раз, если класс имеет только неявные конструкторы, но приложение быстрого тестирования покажет, что конструктор копирования действительно вызывается, если он реализован. Однако я ошибался: конструктор по умолчанию вызывается один раз, а конструктор копирования вызывается 100 раз, а не 99. – Dathan

11

У меня есть вектор, объявленный как глобальная переменная, которую я должен использовать для повторного использования.

Почему? Из вашего кода неясно, почему переменная должна быть глобальной. Почему вы не можете объявить его внутри петля? Тогда вам не нужно его перезагружать, это будет сделано автоматически в каждом цикле.

Чтобы получить доступ к переменной из других методов, передайте ее в качестве параметра (по ссылке, чтобы вы могли ее изменить). Наличие глобальной переменной редко является хорошим решением.

Что-то другое: main обязательно никогда имеют тип возвращаемого void, это недопустимый C++ и многие компиляторы будут отвергать его.

0

Поскольку вы используете конструктор по умолчанию для «Объект», я думаю, вы должны полагаться на емкость вектора, а не на его размер. Таким образом, когда вы вызываете clear(), скорее всего, вы не меняете емкость, заданную вашим векторным конструктором (вы можете удерживать не менее 100 элементов, они уже выделены). Читайте о емкости, запасе и размере и о том, как они отличаются друг от друга (резерв - это вызов, который вы хотите запросить для изменения емкости, я просто укажу его на случай, если вам это нужно).

В любом случае, если вам нужно сбросить объекты до состояния по умолчанию, вместо того чтобы полагаться на возможность выполнять обход объектов в векторном масштабе, вы также можете просто позвонить на свой объект с именем «reset» ", чтобы установить их в это состояние и вызвать его перед повторной обработкой с использованием тех же объектов. По производительности, я не вижу в этом ничего другого, и по коду это кажется чистым решением.

1

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

objVector.resize(0); 
objVector.resize(100); 

ясно() освобождает память вектора на некоторые реализации (его требуется только постусловие что size() = 0). resize (0) поддерживает емкость.

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

+0

На самом деле, я посмотрел. В то время как в C++ 03 оба '.clear()' и '.resize (0)' не могли вызывать перераспределение (потому что это имело бы недействительный '.begin()', который C++ 03 не разрешал) C++ 0x, по-видимому, допускает переключение между '.clear() и' .resize (0) '(поскольку теперь они могут аннулировать' .begin() '). Разумеется, перераспределение не подразумевает изменения емкости, поэтому нельзя утверждать, что подобное «поскольку емкость не изменится, перераспределение не произойдет». Я думаю. –

+0

Молчаливое изменение, которое сделало '.resize (0)' и '.clear()' возможно перераспределением, следующее: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects. html # 414 (обратите внимание, что оба они все еще должны перераспределяться на тот же или больший объем памяти, который хранится в емкости. Поэтому было бы бесполезно перераспределять их. Но теоретически они могут, если бы я это правильно прочитал). –

+0

Хех, это оказалось сложнее, чем я думал. Спасибо за комментарии. – AshleysBrain

2

Почему вы пытаетесь сбросить глобальную переменную? Просто выделите новый вектор каждый раз через цикл и передайте вектор в функции по ссылке.

void ParseFileIntoVector(vector<Object> &vector); 
void ProcessObjectsInVector(const vector<Object> &vector); 

int main() 
{ 
while(THERE_ARE_MORE_FILES_TO_READ) 
{ 
    // Pseudocode 
    vector<Object> objVector(100); 
    ReadFile(); 
    ParseFileIntoVector(objVector); 
    ProcessObjectsInVector(objVector); 
} 
} 
0
Могу ли я переустановить вектор как «векторный объектив (100)», поскольку он был первоначально выделен в стеке?
  1. Векторы C++ не выделяются в стеке. По крайней мере, не напрямую. Одним из параметров для вектора (и других шаблонов STL) является распределитель. Вы можете использовать распределители пулов, распределители кучи и т. Д.

    std::vector<T> на самом деле красиво упакованный указатель на массив с дополнительной информацией (например, размер и емкость). В противном случае размер вектора должен был быть известен заранее (что не требуется).

  2. Фактически в приведенном выше примере std::vector<T> не находится в стеке, а в разделе данных программы (или как это называется на платформах, отличных от ELF).

Таким образом, вопрос, если вам нужно:

  • вектора размера 100. В этом случае, как уже отмечалось, это, вероятно, что вы делаете что-то странное. Но по-прежнему возможно с помощью метода resize.
  • Вектор емкости 100. В этом случае вы, вероятно, ничего не должны делать, поскольку векторы не уменьшают его возможности AFAIR.И, конечно же, это не требуется, поскольку векторы динамически меняют свою емкость.
Смежные вопросы