Получение ссылки на разыменованный элемент из контейнера указателей по диапазонному циклу

Дано контейнер указателей на ints, как я могу увеличить intбез использования оператора разыменования * в теле цикла {}?

Вот реализация с оператором разыменования в теле цикла:

#include <vector>
#include <iostream>
using namespace std;

int main() {
    int x = 0, y = 1, z = 2;

    auto increment_elements = [](vector<int*>& v) {
        for (auto& i : v) { ++*i };
    };

    increment_elements(vector<int*>{&x, &y, &z});

    cout << x << ", " << y << ", " << z << endl;
}

Замена

for (auto& i : v) { ++*i };

с

for (int& i : v) { ++i };

дает MSVC-2013

error C2440: 'initializing' : cannot convert from 'int *' to 'int &',

Почему замена с

for (auto& i : v) { ++i };

компилировать, но не увеличивая intс, а что это делает?

У меня такой же вопрос относительно замены на

for (int*& i : v) ++i;

что дает тот же результат.

2 ответа

Решение

Учитывая контейнер указателей на целые, как я могу увеличивать целые, не используя оператор разыменования * в теле цикла {}?

Использует ссылки на указатели, когда вы можете. Вы не можете сделать вектор ссылочного типа, поэтому вы можете использовать std::reference_wrapper<int>,

std::vector<std::reference_wrapper<int>> v{x, y, z};

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

template<class Iter>
void increment_elements(Iter first, Iter last)
{
    for (; first != last; ++first->get(), ++first);
}

Тогда вы можете позвонить, используя begin() а также end():

increment_elements(std::begin(v), std::end(v));

Или, если вы все еще хотите взять вектор в качестве аргумента, вы можете просто выполнить итерации и увеличить:

for (int& i : v) ++i;

и назовите это как:

increment_elements(v);

Почему замена на [...] компилируется, но без увеличения целых чисел, и что она делает?

auto выводит тип элемента как int* так decltype(i) становится int*& который делает то же самое, что и ваш последний пример.

Ваш вектор vector<int *> не vector<int> !

vector<int *> &v;
for (auto &i : v)
    ++(*i);

v это вектор int *, Итак, тип i является int* &, Поэтому вы должны использовать ++(*i); увеличивать x, y а также z,

for (int &i : v)
    ++i;

Это не верно. v это вектор int *, но вы пытаетесь назначить int * в int &,

for (auto &i : v)
    ++i;

Этот код увеличивает указатели, а не x, y, z, Поскольку он равен

for (std::vector<int *>::iterator it = v.begin(); it != v.end(); ++it)
    ++(*it);
Другие вопросы по тегам