Почему эта арифметика итератора не работает?

Я изучаю C++ для удовольствия. Я пытаюсь понять арифметику итераторов и написал простую программу, которая суммирует первый элемент вектора с последним элементом. Затем суммируются второй и предпоследний элементы. Процесс продолжается до тех пор, пока все элементы не будут суммированы таким образом.

Проблема, похоже, связана с частью *(a.end() - 1 - it) моего кода. Если я уберу - it, то получу ожидаемый результат. Добавление - it приводит к ошибке, говорящей, что

были ошибки сборки. Хотите продолжить последнюю успешную сборку?

Ошибки, которые я получаю от Visual Studio, следующие:

E0075 Операнд * должен быть указателем

C2100 незаконная косвенность

Я уже подошел к этой проблеме по-другому и смог достичь своей цели. Мой вопрос: почему этот код является ошибкой, и можно ли его немного изменить для правильного выполнения?

Я ценю любые советы.

#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main() 
{
    vector<int> a{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    for (auto it = a.begin(); it != a.begin() + (a.end() - a.begin()) / 2; ++it)
        cout << (*it) +  *(a.end() - 1 - it) << endl;

    return 0;
} // END MAIN

Сообщение об ошибке

Список ошибок

iterator - iterator дает расстояние, а не итератор.
Jarod42 23.12.2020 17:19

Если вы получили ошибку компилятора, почему вы не указали точную ошибку в этом вопросе?

EOF 23.12.2020 17:26

Спасибо за добавление ошибок, стало намного лучше. Обратите внимание, что изображения, к сожалению, не всем легко читать. Не могли бы вы добавить текст сообщения об ошибке к вопросу? Просто строка «косвенность требует ...» в порядке. Наличие изображений также прекрасно.

cigien 23.12.2020 17:45

Спасибо за добавление текста, теперь вопрос довольно приятный. Я немного отредактировал его, чтобы улучшить форматирование. Конечно, есть и другие способы сделать это, но этот может дать вам некоторые идеи.

cigien 23.12.2020 18:04
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
334
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Вычитание 2 итераторов с помощью a.end() - 1 - it дает вам расстояние между ними. Вы не можете разыменовать расстояние с помощью *, поэтому вы получите ошибку компилятора.

Это расстояние от a.begin() до элемента, который вы хотите получить, необходимо в выражении. Вы можете немного изменить выражение, просто добавив a.begin() к этому расстоянию:

 cout << (*it) +  *(a.end() - 1 - it + a.begin()) << endl;
                                 //  ^^^^^^^^^^^

Вот демо.


Начиная с C++20, вместо того, чтобы иметь дело с итераторами и манипулировать ими, вы можете напрямую работать с диапазонами, что может быть легче читать, когда вы к этому привыкнете:

// just for convenience
namespace sv = std::views;
namespace sr = std::ranges;

// size of half the range
auto half = a.size() / 2;
 
sr::transform(a | sv::take(half),                          // first half
              a | sv::reverse | sv::take(half),            // second half reversed
              std::ostream_iterator<int>(std::cout, "\n"), // print out
              std::plus{});                                // the sum

Вот демо.

Спасибо, cigien. Ваш ответ был очень полезен. Кажется, я понимаю, где ошибся в своих размышлениях. Еще раз спасибо.

AdamsK 23.12.2020 17:30

@AdamsK Нет проблем. Как упоминалось в комментарии к вашему вопросу, вам не хватает сообщения об ошибке компилятора. Пожалуйста, добавьте это к вопросу, чтобы сделать вопрос более полезным, а также соответствовать правилам сайта.

cigien 23.12.2020 17:31

@fabian Конечно, есть разные способы сделать код более читабельным. Однако я бы не стал заявлять, что какая-либо версия более производительна, чем другая, без бенчмаркинга и предварительного профилирования кода.

cigien 23.12.2020 18:11

Вы должны изменить код следующим образом:

auto fix = it - a.begin();

cout << (*it) + *(a.end() - 1 - fix) << endl;

вы не можете манипулировать итераторами, такими как целые числа, вы просто можете просто добавлять или добавлять целые числа или использовать начальную точку из begin() - поскольку end() не является реальным указателем на какое-то значение в векторе.

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