Я пытаюсь думать о методе, демонстрирующем своего рода ошибку памяти с помощью Массивов и C++, который трудно обнаружить. Цель состоит в том, чтобы мотивировать использование вектора STL <> в сочетании с итераторами.
Править: Принятый ответ является ответом, я раньше объяснял преимущества / недостатки. Я также использовал: это
Утечка памяти? IMO, вектор в сочетании с итераторами не особо защищает вас от ошибок, таких как выход за пределы или вообще использование недействительного итератора (если у вас нет VC ++ с отладкой итератора); скорее это удобно, потому что он реализует для вас динамически изменяемый размер и заботится об управлении памятью (NB! помогает сделать ваш код более безопасным для исключений).
void foo(const char* zzz)
{
int* arr = new int[size];
std::string s = zzz;
//...
delete[] arr;
}
Вышеупомянутая информация может просочиться в случае возникновения исключения (например, при создании строки). Не с вектором.
Vector также упрощает рассуждения о коде из-за его семантики значений.
int* arr = new int[size];
int* second_ref = arr;
//...
delete [] arr;
arr = 0; //play it safe :)
//...
second_ref[x] = y;
//...
delete [] second_ref;
Но, возможно, вектор автоматически не удовлетворяет 100% случаев использования динамического массива. (Например, есть также boost :: shared_array
и будущий std :: unique_ptr
)
Я думаю, что полезность std::vector действительно проявляется, когда вам нужны динамические массивы.
Сделайте один пример с использованием std::vector. Затем один пример с использованием массива для перераспределения. Я думаю, это говорит само за себя.
Я думаю, что простота использования векторов
вместо динамических массивов уже убедительна.
vector
(Google говорит по состоянию на 2003 год, см. 23.2.4./1 спецификации). векторе
, но не о вашей странности. С динамическим массивом вам нужно самостоятельно отслеживать размер, увеличивать его, когда вы хотите вставить новые элементы, и удалять, когда он больше не нужен ... это дополнительная работа.
Ой. и предупреждение: vector
- это грязный тухлый взлом и классический пример преждевременной оптимизации.
void Fn()
{
int *p = new int[256];
if ( p != NULL )
{
if ( !InitIntArray( p, 256 ) )
{
// Log error
return;
}
delete[] p;
}
}
Вы не поверите, как часто я это вижу. Классический пример того, где любая форма RAII полезна ...
Неправильное сопряжение new/delete и new[]/delete[].
Например, использование:
int *array = new int[5];
delete array;
вместо:
int *array = new int[5];
delete [] array;
И хотя стандарт c++ не позволяет этого, некоторые компиляторы поддерживают выделение массива стеком:
int stack_allocated_buffer[size_at_runtime];
Это может быть непредусмотренным побочным эффектом правил скопирования (например, константа, затененная переменной-членом)... и это работает, пока кто-то не передаст 'size_at_runtime' слишком большим и не снесет стек. Тогда возникают отстойные ошибки.
Один очевидный:
for (i = 0; i < NUMBER_OF_ELEMENTS; ++i)
destination_array[i] = whatever(i);
против
for (i = 0; i < NUMBER_OF_ELEMENTS; ++i)
destination_vector.push_back(whatever(i));
указывая на то, что вы знаете, что второе работает, но работает ли первое, зависит от того, как был определен destination_array
.
Почему бы вам не мотивировать это на основе алгоритмов, которые предоставляет STL?
В сыром массиве operator[] (если можно так выразиться) подвержен проблеме index-out-of-bound. С вектором это не так (есть, по крайней мере, исключение во время выполнения).
Извините, я недостаточно внимательно прочитал вопрос. index-out-of-bound - это проблема, но не ошибка памяти.