2010-03-05 6 views
4
std::vector<Foo> vec; 
Foo foo(...); 

assert(vec.size() == 0); 
vec.reserve(100); // I've reserved 100 elems 
vec[50] = foo; // but I haven't initialized any of them 
// so am I assigning into uninitialized memory? 

Является ли вышеуказанный код безопасным?Является ли следующий код std :: vector действительным?

+1

Вообще говоря, я предпочитаю использовать 'at' to' operator [] '. Хотя он семантически идентичен и немного длиннее для записи, он имеет так называемую функцию «проверки границ». Я бы никогда не подумал о том, что пишет за пределами границ как «безопасный» ... –

+0

@Matthieu: Я этого не знал. +1. –

ответ

7

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

Дело в том, что вы не можете изменять размер вектора без инициализации элементов (даже если только инициализация по умолчанию).

0

Это не сработает. В то время как контейнер содержит 100 элементов, он все еще имеет 0 элементов.

Вам необходимо вставить элементы, чтобы получить доступ к этой части памяти. Как сказал Джон-Эрик, resize() - это путь.

4

Вы должны использовать vec.resize(100), если хотите сразу же проиндексировать.

vec[50] безопасно только если 50 < vec.size(). reserve() не изменяет размер вектора, но resize() делает и строит содержащийся тип.

0

std :: vector :: reserve (100) будет требовать 100 * sizeof (Foo) свободной памяти, так что дальнейшая вставка в вектор не будет выделять память до 100 * sizeof (foo), но доступ к элементу этого вектора даст неопределенный контент этого элемента, поскольку его единственное требование - память не выделяет его.

0

Прежде чем вы сможете использовать оператор [] для доступа к 50-му элементу, вы должны либо вызвать resize, push_back() что-то 50 раз, либо использовать std :: fill_n алгоритм.

+0

'std :: uninitialized_fill_n' не лучше того, что он делает. – Potatoswatter

+0

Вы правы, fill_n() требует, чтобы элементы вектора были инициализированы. Но я предполагаю, что вместо этого можно использовать std :: generate(). –

+0

Нет, 'generate' с простой функцией ничем не отличается от' fill_n', которая не так близка к тому, что мы хотим, как 'uninitialized_fill_n'. Нет универсального алгоритма, который будет работать здесь, потому что STL algos изменяет последовательности, а не контейнеры. «Back_insert_iterator» был бы обходным путем, если вы настроены на использование ''. – Potatoswatter

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