В C ++ всегда предпочитайте контейнеры необработанным указателям или массивам, если это возможно.
Типы массивов в сигнатурах функций на самом деле являются указателями.Все следующие три объявления абсолютно одинаковы:
void foo(int a[10]);
void foo(int a[]);
void foo(int* a);
Во всех трех случаях foo
принимает один параметр: указатель на int
.Когда вы передаете массив этой функции, он неявно распадается на указатель на свой первый элемент.
Когда массив распадается на указатель, длина массива теряется.Это означает, что следующий код скомпилируется, но логически неверен:
void foo(int a[10]) {
for (size_t i = 0; i < 10; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
// Whoops, wrong size array!
int arr[5] = {};
foo(arr);
}
Live Demo
Объявление длины, в данном случае, является полной и полной ложью,Запись бессмысленного числа в определении функции просто увеличивает риск того, что кто-то допустит ошибку.
Если вы должны использовать необработанные указатели для параметра функции, принимающего массив, ваша функция также должна принять параметр размера:
void foo(int* a, size_t length) {
for (size_t i = 0; i < length; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
int arr[5] = {};
foo(arr, 5);
}
Live Demo
Это также опасно, так как кто-то может полностью пропустить неправильный размер и вызвать ошибки:
void foo(int* a, size_t length) {
for (size_t i = 0; i < length; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
int arr[5] = {};
//Whoops, passed the wrong size!
foo(arr, 10);
}
Live Demo
По этой причине вы должны предпочесть использовать контейнер:
void foo(const std::vector<int>& a) {
for (int i : a) {
std::cout << i << '\n';
}
}
int main() {
std::vector<int> arr(5);
foo(arr);
}
Live Demo
Если вы не знаете, какой тип контейнера использовать;по умолчанию std::vector
.Если ваша функция должна поддерживать несколько типов контейнеров, используйте шаблон:
template <typename Container>
void foo(const Container& a) {
for (int i : a) {
std::cout << i << '\n';
}
}
int main() {
std::vector<int> arr(5);
foo(arr);
std::array<int, 5> arr2 = {};
foo(arr2);
}
Live Demo