2012-05-24 4 views
0

У меня есть фрагмент кода, где я сначала поместил некоторые значения в std::vector, а затем дал адрес каждого из них одному из объектов, которые будут использовать их, например:Перераспределение в std :: vector после std :: vector.reserve()

std::vector <useSomeObject> uso; 

// uso is filled 

std::vector <someObject> obj; 

for (int i=0; i < numberOfDesiredObjects; ++i){ 
    obj.push_back(someObject()); 
    obj.back().fillWithData(); 
} 
for (int i=0; i < numberOfDesiredObjects; ++i){ 
    uso[i].setSomeObject(&obj[i]); 
} 

// use objects via uso vector 
// deallocate everything 

Теперь, так как я иногда немного в стиле урод, я думаю, что это некрасиво и хотел бы использовать только один цикл, вроде как это :

for (int i=0; i < numberOfDesiredObjects; ++i){ 
    obj.push_back(someObject()); 
    obj.back().fillWithData(); 
    uso[i].setSomeObject(&obj.back()); 
} 

Конечно, я не могу этого сделать, потому что иногда происходит перераспределение, и все указатели, которые я установил, стали недействительными.

Итак, мой вопрос: Я знаю, что std::vector.reserve() это путь, если вы знаете, сколько вам нужно и хотите выделить память заранее. Если я сделаю уверенным, что, что я пытаюсь выделить достаточно памяти заранее с reserve(), это гарантирует, что мои указатели останутся в силе?

спасибо.


Sidenote.This - аналогичный вопрос, но нет ответа на то, что я хотел бы знать. Просто чтобы он не появился в качестве первого комментария к этому вопросу.

ответ

4

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

Да, это гарантирует ваши указатели будут оставаться в силе, если:

  • The размер возрастает за текущий мощности или
  • Если вы не стереть какие-либо элементы, которые вам нет.

итератора правил для признания недействительными вектора указаны в 23.2.4.3/1 & 23.2.4.3/3 как:

Все итераторы и ссылки до точки вставки, не изменяются , если новый размер контейнера больше, чем предыдущая емкость (в этом случае все итераторы и ссылки недействительны)

Каждый итератор и ссылка после точки стирания недействительны.

5

Это, по сути, одна из основных причин использования reserve.You гарантируют, что добавление к концу std::vector не будет аннулировать итераторы, ссылки или указатели на элементы в векторе , если новый размер вектора не превышает старую емкость.

+0

Я научил основную причину, чтобы попытаться избежать многих перераспределений. Если бы это было причиной, это не нанесло бы слишком много урона, если бы это не удавалось, и перераспределение еще не было выполнено. Таким образом, гарантируется, что в случае сбоя 'reserve()' он будет кричать громко и не просто спокойно продолжать прог. исполнение? – penelope

+1

@penelope: Если новый размер больше текущей емкости (именно это резерв гарантирует выполнение вашего требования), то произойдет передислокация. –

+1

@penelope Послесловие 'std :: vector <> :: reserve (n)' является 'std :: vector <> :: capacity()> = n'. Если новое распределение не удастся, вы получите исключение. –

Смежные вопросы