Я получил задание для реализации массива шаблонов с итератором и для наложения некоторых операторов моего итератора, и у меня есть несколько вопросов.
Из того, что я понимаю, стандартный итератор с произвольным доступом позволяет вам превышать массив. Позволяет ли он получить значение, которое он держит над размером?
Позволяет ли пользователь перезаписывать эту память?
И для моей реализации, я должен разрешить доступ через размер?
я должен позволить получить данные из размера?
я должен позволить любое изменение к нему?
что считается хорошим программированием в этом случае?
Любая помощь будет высоко ценится
Я думаю, что вы, возможно, слишком много читаете в своем задании, но ваши вопросы, тем не менее, заслуживают рассмотрения.
Прежде всего, некоторые соображения:
iterator
а также const_iterator
в общем случае вложенные типы), первый позволяет писать в элемент, на который указывает указатель, а второй — нет.Теперь, что касается ваших вопросов, действительно есть дизайнерское решение о том, следует ли выполнять проверка границ или нет.
В общем, итераторы в C ++ настолько легки, что не выполняют никакой проверки границ. Это имя эффективности и вы не платите за то, что не используете философии. Если пользователь когда-либо промахнется … она станет жертвой Неопределенное поведение, это все может случиться.
Однако большинство (если не все) реализации STL также признают проблему и предоставляют режим отладки (проверенный режим), который вы можете использовать при тестировании своего приложения; конечно, они приводят к дополнительным затратам не только с точки зрения процессора, но и с точки зрения памяти.
Таким образом, вы сами выбираете, предоставлять чеки или нет, и, возможно, предоставлять их по желанию. Я бы порекомендовал начать без проверок, и только закрепите их позже, так как у вас есть лучшее представление о том, как выглядит система.
Количество проверок во время выполнения, выполняемых итераторами, зависит от них. std
Библиотечные итераторы обычно очень мало проверяют во время выполнения, как часть философии проектирования std
библиотека предназначена для обеспечения производительности контейнера, закодированного вручную, с помощью высокоуровневой проверки типов.
Тем не менее, многие std
Реализации библиотеки включают несколько уровней проверки во время выполнения в качестве опции для отладочных сборок. Это означает, что если вы запрашиваете содержимое недействительного итератора, std
Итератор вызовет неопределенное поведение и, возможно, выдаст вам содержимое некоторой случайной памяти после конца буфера, или, иногда, сегфоута. И если вы напишите, он с радостью запишет в ту память, в которую вам запрещено писать.
Когда вы пишете итератор, было бы неплохо включить средства отладки в итератор, потому что вы не будете писать его правильно с первого раза. В то время как std
Инструменты отладки итератора библиотеки в основном предназначены для того, чтобы поймать пользователя итератора, совершившего ошибку, причем проверки, которые вы хотите выполнить, чтобы определить, будет ли автор итератора ошибаться (т. е. вас), будут аналогичными.
Хорошей практикой было бы включать и не включать такие проверки. И вы обязательно должны включить такие проверки (подключенные к исключению, утверждению или даже просто к системе регистрации ошибок — cerr
в этом контексте считается записью ошибок) при разработке ваших итераторов, даже если проверки можно отключить или удалить в «производственном» коде.
Размер не важен для переполнения. Итератор произвольного доступа означает, что вы можете искать элемент с помощью оператора [] или увеличивать или уменьшать его на произвольную величину с помощью оператора + = или + или — = или —
Посмотреть все необходимые операции здесь http://www.cplusplus.com/reference/iterator/RandomAccessIterator/
В стандартной библиотеке C ++ (ранее известной как STL) итераторы не выполняют проверку диапазона так же, как в указателях C не выполняют проверку диапазона. Доступ к памяти через итератор, указывающий за выделенные границы, является неопределенным поведением, точно так же, как доступ к памяти через указатель, который указывает за выделенными границами, является неопределенным поведением. Вы должны следовать тому же принципу при разработке ваших итераторов, то есть вы не должны выполнять никаких проверок границ при доступе к данным.
Из того, что я понимаю, стандартный итератор с произвольным доступом позволяет вам превышать массив.
Не совсем; вы не можете получить доступ к чему-либо вне контейнера, и попытка сделать это даст неопределенное поведение. Но итератор не обязывает вас пытаться получить доступ к недопустимой памяти.
Причина в том, что для проверки диапазона могут быть значительные затраты времени выполнения; не требуя этого, вы можете выбирать между быстрой реализацией, которая требует правильного проектирования шаблонов доступа, или медленной, более безопасной реализацией, которая может обнаружить некоторые ошибки для вас.
Позволяет ли он получить значение, которое он держит над размером? Позволяет ли пользователь перезаписывать эту память?
Это может обнаружить это и сообщить об ошибке; или это не так, и позволит вам получить доступ к недействительной памяти с неопределенными результатами.
И для моей реализации, я должен разрешить доступ через размер?
Нет, нет смысла разрешать Это. Вы можете выбрать, следует ли активно предотвращать это, проверяя доступ во время выполнения, или пассивно предотвращать это, документируя, что ответственность за то, чтобы итератор оставался действительным, лежит на пользователе.
что считается хорошим программированием в этом случае?
Непроверенный итератор проще и не добавляет, возможно, нежелательных затрат на производительность. Вы можете также предоставить проверенные итераторы; либо отдельно, либо в качестве оберток вокруг непроверенных, чтобы дать пользователю выбор того, насколько быстро или безопасно он этого хочет.