C++ массивы (std::array)
Концепты
Заголовок раздела «Концепты»- Преимущество C++ массивов над C массивами
- Копирование и инициализация массивов
- Индексирование C++ массивов
data- Получение ссылок на элементы массива
- Получение адресов элементов массива
- Типы данных кроме
intпод элементы массива
Примеры
Заголовок раздела «Примеры»1. С++ массивы
Заголовок раздела «1. С++ массивы»std::array<int, 2> arr{ 1, 2 };int* pa = a.data();int& b = *pa;pa += 1;std::cout << b << std::endl;
Что такое data?
data?a.data() дает адрес первого элемента из массива
(&a[0], a[0] дает ссылку, потом берем адрес из ссылки).
Ответ
b будет продолжать ссылаться на первый элемент, несмотря на то, что указатель обновился.
2. Инициализация C++ массивов (1)
Заголовок раздела «2. Инициализация C++ массивов (1)»std::array<int, 2> arr{ 1, 2 };std::array<int, 2> other{ 3, 4 };arr = other;Ответ
Тут каждый элемент копириуется из other в arr.
3. Инициализация C++ массивов (2)
Заголовок раздела «3. Инициализация C++ массивов (2)»std::array<int, 2> arr{ 1, 2 };std::array<int, 2> other{ arr };Ответ
Тут тоже, но при создании other.
4. Ссылка на массив
Заголовок раздела «4. Ссылка на массив»std::array<int, 2> arr{ 1, 2 };std::array<int, 2>& other{ arr };other[0] = 3;std::cout << arr[0] << std::endl;Ответ
Здесь иллюстрируется создание ссылки на объект типа С++ массива.
other как бы заменяете на arr.
5. Адрес массива
Заголовок раздела «5. Адрес массива»std::array<int, 2> arr{ 1, 2 };std::array<int, 2>* p{ &arr };*p = { 3, 4 };std::cout << arr[0] << std::endl;std::cout << arr[1] << std::endl;Ответ
p будет содержать адрес начала всего объекта массива.
Объект массива покрывает все его элементы.
Здесь, изначальные элементы перезаписываются на 3, 4.
6. Dereference адреса массива
Заголовок раздела «6. Dereference адреса массива»std::array<int, 2> arr{ 1, 2 };std::array<int, 2>* p{ &arr };std::array<int, 2> arr1{ *p };arr1[0] = 3;arr1[1] = 4;std::cout << arr[0] << std::endl;std::cout << arr[1] << std::endl;Ответ
Тип у p это std::array<int, 2>, выражение *p даст значение
типа std::array<int, 2>, то есть в arr1 попадет копия всего массива
Поскольку arr1 это копия, ее изменения не повлияют на arr.
7. Ссылка на элемент массива
Заголовок раздела «7. Ссылка на элемент массива»std::array<int, 2> arr{ 1, 2 };int& a = arr[0];a = 3;Ответ
a = 3 перезаписывает первый элемент массива,
поскольку в a была сохранена ссылка на 1 элемент (на объект внутри массива).
8. Индексирование элементов из адреса
Заголовок раздела «8. Индексирование элементов из адреса»std::array<int, 2> arr{ 1, 2 };std::array<int, 2>* p{ &arr };(*p)[0] = 3;(*p)[1] = 4;std::cout << arr[0] << std::endl;std::cout << arr[1] << std::endl;Ответ
Здесь, *p — это выражение типа std::array<int, 2>&, то есть дает ссылку на массив,
на память переменной arr (потому что в p адрес arr).
Индексирование относительно (*p) будет давать ссылки на элементы в массиве.
Например, тип выражения (*p)[0] — это int&, а ссылаться это будет
на первый элемент в массиве, в переменной arr.
Перезапись также будет применяться к элементам arr.
9. Адрес элемента через data
Заголовок раздела «9. Адрес элемента через data»std::array<int, 2> arr { 1, 2 };int& arr1 = *(p.data() + 1)Ответ
Аналогично коду выше, только выражение сложнее.
Тут в arr1 попадает адрес arr[1].
10. Взаиморасположение базового адреса и самого объекта массива
Заголовок раздела «10. Взаиморасположение базового адреса и самого объекта массива»std::array<int, 2> arr { 1, 2 };ptrdiff_t diff { reinterpret_cast<uint8_t*>(arr.data()) - reinterpret_cast<uint8_t*>(&arr) };std::cout << diff << std::endl;Ответ
Начало всего массива находится там же, где и первый элемент массива.
Массив std::array это и есть его элементы.
Выведется 0.
11. Матрицы (двумерные массивы)
Заголовок раздела «11. Матрицы (двумерные массивы)»std::array<std::array<int, 2>, 3> arr{ std::array{ 1, 2 }, { 3, 4 }, { 5, 6 },};std::array<int, 2> firstRow { arr[0] };std::array<int, 2> lastRow { arr[2] };arr[0][0] = 7;arr[2][1] = 8;arr[1] = { 9, 10 };Ответ
Тут иллюстрируется использование массива, где тип элемента не int, а массив.
Каждый элемент массива по сути теперь хранит в себе по два инта.
В инициализации
arrнеобходимо указатьstd::array, потому что иначе компилятор не может определить тип элемента из инициализации. Ему нужно слегка помочь.Механизм этого вам пока не обязательно понимать.
Можно ли использовать пользовательский тип как элемент массива?
Можно. Попробуйте определить тип, например:
struct Item{ int f1; int f2;};И использовать его в качестве типа элемента, вот так:
std::array<Item, 3> arr{ Item{ 1, 2 }, { 3, 4 }, { 5, 6 },};