Я изучаю 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
Если вы получили ошибку компилятора, почему вы не указали точную ошибку в этом вопросе?
Спасибо за добавление ошибок, стало намного лучше. Обратите внимание, что изображения, к сожалению, не всем легко читать. Не могли бы вы добавить текст сообщения об ошибке к вопросу? Просто строка «косвенность требует ...» в порядке. Наличие изображений также прекрасно.
Спасибо за добавление текста, теперь вопрос довольно приятный. Я немного отредактировал его, чтобы улучшить форматирование. Конечно, есть и другие способы сделать это, но этот может дать вам некоторые идеи.
Вычитание 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 Нет проблем. Как упоминалось в комментарии к вашему вопросу, вам не хватает сообщения об ошибке компилятора. Пожалуйста, добавьте это к вопросу, чтобы сделать вопрос более полезным, а также соответствовать правилам сайта.
@fabian Конечно, есть разные способы сделать код более читабельным. Однако я бы не стал заявлять, что какая-либо версия более производительна, чем другая, без бенчмаркинга и предварительного профилирования кода.
Вы должны изменить код следующим образом:
auto fix = it - a.begin();
cout << (*it) + *(a.end() - 1 - fix) << endl;
вы не можете манипулировать итераторами, такими как целые числа, вы просто можете просто добавлять или добавлять целые числа или использовать начальную точку из begin() - поскольку end() не является реальным указателем на какое-то значение в векторе.
iterator - iterator
дает расстояние, а не итератор.