Комментарии 21
я конечно всё понимаю, но указатель это и тоже итератор
На самом деле, на сегодняшний день уже вообще нет особого смысла использовать голые/сырые указатели (raw pointers).
Ну напишите без них свой аллокатор...
heap действительно переводится как "куча"?
Вам встречались другие варианты? Возможно в художественном переводе в каких то контекстах адекватнее другие синонимы, но в технических текстах о выделении памяти альтернатив не видел.
Когда я писал на С++ (это было давно), писали просто - область памяти в хипе. И все было понятно.
Я других вариантов никогда не видел.
Упоминание контейнеров STL также не спроста — итераторы нельзя использовать с C-массивами.
А вот и неправда:
int foobar(int n)
{
int a[] = {1, 2, 3, 5, 9};
auto it = std::find(std::begin(a), std::end(a), n);
if(it != std::end(a))
return std::distance(std::begin(a), it);
return -1;
}
это же по сути обертка над сырым указателем. сами по себе C-style массивы не умеют так делать, просто конструктор итератора позволяет сделать итератор из указателя
Просто пойнтер поддерживает то, что необходимо итератору с произвольным доступом, и никакой дополнительный итератор из него конструировать не надо.
это же по сути обертка над сырым указателем
Так и в std::array итератор - тоже обёртка над сырым указателем. Они вообще между собой ничем не отличаются, даже типом:
int a[] = {1, 2, 3};
std::array<int, 3> b = {1, 2, 3};
auto it1 = std::begin(a);
auto it2 = std::begin(b);
std::cout << typeid(it1).name() << std::endl;
std::cout << typeid(it2).name() << std::endl;
Выведет для g++ и clang++:
Pi
Pi
Т.е. указатели на int, в данном случае.
сами по себе C-style массивы не умеют так делать
Вопрос был в том, можно ли итераторы использовать для работы с ними, или нет, а не в том, что умеют или не умеют массивы сами по себе.
На самом деле, на сегодняшний день уже вообще нет особого смысла использовать голые/сырые указатели (raw pointers).
Core Guidelines с вами не согласен.
Passing a smart pointer transfers or shares ownership and should only be used when ownership semantics are intended. A function that does not manipulate lifetime should take raw pointers or references instead
Вообще, я бы вам рекомендовал не пытаться изобретать велосипеды, а потратить силы на перевод того, что уже хорошо написано и неплохо обосновано, от этого будет больше пользы.
Учитывая, что указатель всегда хранит адрес памяти, его всегда можно преобразовать в целое число (которое и является адресом).
Штош :) Рекомендую вам ознакомиться с интересной статьёй на тему указателей на методы класса)
Pointers to member functions are very strange animals
Ну или хотя бы заглянуть в этот топик на Stackoverflow. Вас ждёт сюрприз :)
Ну и если уж подняли тему невалидных указателей, то имеет смысл и поднять тему инвалидации итераторов, потому как это чуть ли не самая важная штука.
С++ - это про оптимизацию.
С подходом, описанным в этой статье, надо писать на Java. Да, современные компиляторы часто справляются превратить смартпоинтеры в указатели обратно, или контейнеры в С массивы (которые при обходе быстрее). Но чтобы кмпилятор это мог сделать надо ему помогать. А высказывания в духе "не пользуйтесь сырыми указателями / С массивами никогда" вызывает вопрос: а зачем тогда пользоваться крестами?
Правило #1 в плюсах - zero abstraction cost. Собственно из-за него многое в плюсах ТАК неудобно. Поэтому в подавляющем большинстве случаев совет, в целом, верный и пользование unique_ptr будет бесплатным.
С shared_ptr сложнее, но этот указатель и не нужен практически никогда, а если нужен, нужно четырежды поднимать "а точно ли нужен?".
Для замены С-массивам давно есть std::array, который в сочетании с CTAD из С++17 вроде даже удобно использовать (не обязательно вручную задавать размерность).
И всё это в целом-то бесплатно. Так что ничего ужасного в совете как таковом нет. А вот в подаче да, проблема есть. В статье делается несколько ультимативных заявлений, без внятного объяснения, и, что хуже всего, без хороших примеров и рассмотрения крайних случаев. Что сильно снижает ценность статьи.
Допустим у нас есть карта - двумерный массив и некий агент. Мы хотим проитерировать клетки перед агентом. Но в зависимости от направления итерировать надо или по x или по y. В голову приходит примерно такой подход:
...
int i, xi, yi;
...
switch (direction)
{
case 0:
xi = x + 1;
yi = y - 1;
iter = &yi;
case 1:
xi = x - 1;
yi = y + 1;
iter = ξ
....
}
for (i = 0; i < 4; i++)
{
scan(cell[xi][yi]);
(*iter)++;
}
Как грамотно решать эту задачу на современном C++ ?
Вспомнилась статья "Что должен знать каждый программист о памяти". Там тоже был обход массива)
Основы C++: Указатели и Итераторы