В чем причина использования &*beg вместо beg, если beg является итератором?

В книге «Экскурсия по C++» (третье издание для C++20) Бьярна Страуструпа, раздел 18.5.2 упакованной задачи, у нас есть этот фрагмент кода:

// compute the sum of [beg:end) starting with the initial value init 
double accum(vector<double>::iterator beg, vector<double>::iterator end, double init)
{
     return accumulate(&*beg, &*end, init);
}

Почему Страуструп использовал здесь &* итератора вместо самого итератора? Есть ли какое-либо преимущество или разница в этом?

Подумайте о том, что std::vector<double>::iterator::operator* на самом деле делает/возвращает. Вероятно, здесь есть обман.

G.M. 07.08.2024 19:02

это ошибка? Нет, это очень намеренно. Это точка обучения. И это не работает для других типов контейнеров, которые не хранят свои элементы последовательно.

Eljay 07.08.2024 19:04

вы получите ссылку на double, но накопление принимает итератор в качестве параметра

kingsjester 07.08.2024 19:06

вы получите ссылку на двойной Не совсем верно. Вы возразите double*, который сам по себе (в данном случае) является допустимым итератором.

Eljay 07.08.2024 19:07

Так почему же предпочесть double* std::vector<double>::iterator ?

kingsjester 07.08.2024 19:07

Я очень надеюсь, что позже он скажет, что &*end — это неопределенное поведение (при условии, что end получено из метода end()).

Yksisarvinen 07.08.2024 19:08

Это хороший вопрос. Я тоже не вижу здесь преимущества. Я бы перечитал раздел, где это делается, чтобы посмотреть, объяснит ли он свои рассуждения несколькими страницами раньше или позже.

user4581301 07.08.2024 19:09

@Yksisarvinen совсем нет!

kingsjester 07.08.2024 19:10

Примечание: здесь не используется stl. stl относится к стандартной библиотеке шаблонов, чрезвычайно влиятельной библиотеке 1990-х годов, которая послужила источником огромного вдохновения и во многих случаях стала ранними реализациями стандартной библиотеки C++. Даже 25 лет спустя часто можно увидеть отголоски в названии деталей реализации.

user4581301 07.08.2024 19:14

@kingsjester Даже итераторы в непрерывной памяти иногда оборачиваются какими-то причудливыми вещами (то есть не всегда необработанными указателями) для целей отладки и т. д. Разыменовывая итератор и беря адрес объекта, вы получаете необработанный указатель - и, предположительно, быстрее итерация. Хотя я не понимаю, зачем это в книге...

Ted Lyngmo 07.08.2024 19:15

Так почему же предпочесть double*std::vector<double>::iterator? Я думаю, это было просто для примера параллелизма, когда вектор накопления разделяется на отдельные части. Сейчас читаю 18.5.2, разочарован тем, что оплошность &*end не была выявлена. Это ошибка, исправленная в опечатке.

Eljay 07.08.2024 19:16

@Элджей, спасибо, опубликуй это как ответ, и я приму его

kingsjester 07.08.2024 19:18

@Eljay, «мы не должны передавать пары указателей, если вместо этого мы можем использовать диапазон» на самом деле не говорит о том, что это вообще была ошибка.

Ted Lyngmo 07.08.2024 19:18

@TedLyngmo • Верно, не указано явно. Избежал ошибки, избавившись от оскорбительного кода, сделав его немного по-другому и продемонстрировав span. Я позволю кому-то другому дать лучший ответ. (Я уже достаточно побеспокоил Бьярна в этом году.)

Eljay 07.08.2024 19:20

Дубликат решает потенциальную проблему с кодом, но не объясняет, почему Страуструп решил использовать здесь именно этот трюк.

user4581301 07.08.2024 19:28

@user4581301 user4581301 Технически это правда. Учитывая опечатки, это, скорее всего, ошибка, поэтому я не уверен, что очень полезно иметь для этого отдельный вопрос (особенно тот, на который, вероятно, сможет ответить только Страуструп, если они еще не задокументировали его где-нибудь). В качестве альтернативы, дубликат цели можно отредактировать, добавив вопрос «почему Страуструп сделал это», а затем ответить на адрес, который можно добавить туда. Если ни одно из вышеперечисленных решений не является хорошим решением, у меня нет сильных чувств по поводу использования этой цели для обмана.

cigien 07.08.2024 19:40

@cigien Ни я, ни я бы удалили его, а не просто прокомментировали, но Элджей отмечает в комментарии выше, что этот фрагмент кода исправлен в опечатках. Это в значительной степени приводит к ответу: «Ой».

user4581301 07.08.2024 20:03

Было время, когда не существовало концепции непрерывных итераторов, когда необработанные указатели могли использоваться функцией, которой требовался непрерывный диапазон.

François Andrieux 07.08.2024 20:13
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
18
138
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как указал Элджей в комментарии, тот факт, что Б. Страуструп использует здесь double* вместо std::vector<double>::iterator, в данном случае кажется ошибкой, поскольку он исправил это в опечатке. Этот синтаксис представляет собой неопределенное поведение, как описано в этом ответе.

Другие вопросы по теме