Можно ли изменять объекты с помощью std :: for_each? - PullRequest
7 голосов
/ 04 апреля 2009

for_each принимает InputIterators:

//from c++ standard
template <class InputIterator, class Function>
   Function for_each (InputIterator first, InputIterator last, Function f);

Можно ли изменить объект в функции f следующим образом:

struct AddOne
{
    void operator()(int & x){x = x + 1;}
};

std::vector<int> vec(10);
std::for_each(vec.begin(),vec.end(),AddOne());

Этот код работает в VC ++ 2008, а также с GCC, но является ли он также переносимым (легальным) кодом?
(InputIterators гарантированно будут использоваться только как rvalue, в этом случае они используются как lvalue в операторе AddOne ())

Ответы [ 5 ]

7 голосов
/ 04 апреля 2009

Читать статья .

Быть педантичным: for_each - не модифицирующая последовательность операций. Намерение не состоит в том, чтобы изменить последовательность. Тем не менее, это нормально, чтобы изменить последовательность ввода при использовании for_each.

4 голосов
/ 04 апреля 2009

Вы что-то не так поняли. Сказать, что входные итераторы гарантированно пригодны для использования, так как rvalues ​​не означает, что вы не можете каким-то образом получить lvalue из итератора. Так что это не означает, что результат *iterator является значением. То, что вы / for_each передает AddOne, является результатом operator* - , а не самого итератора.

О for_each и объекте модифицирующей функции - прочитайте этот вопрос

3 голосов
/ 06 апреля 2009

Если вы сомневаетесь, используйте std :: transform, так как он сообщит даже случайному читателю вашего кода, что вы намереваетесь что-то изменить.

2 голосов
/ 04 апреля 2009

Это допустимо - входные итераторы используются для указания диапазона, а не для обработки.

Интересно, что Джосуттис в своей книге «Стандартная библиотека C ++» перечисляет for_each как модифицирующее, более редкое, чем немодифицирующее.

0 голосов
/ 08 апреля 2018

Мое предложение было бы, все это имеет значение, как вы передаете свой элемент в функцию, то есть по ссылке или по указателю и изменить его или как копию и изменить его.

Но, как уже говорили другие, если вы хотите изменить значения, лучше использовать transform, так как он заботится о возвращаемых значениях.

    class MultiplyBy {
    private:
        int factor;

    public:
        MultiplyBy(int x) : factor(x) {
        }

        int operator () (int other) const {
            other = factor + other;
            return other; 
          } 

    //  int operator () (int & other) const { 
    //         other = factor + other;
    //         return other;        
    //     }      
    };

        vector<int> x1= {1, 2, 3, 4, 5};
        vector<int> x2;   
        std::transform(x1.begin(), x1.end(), back_inserter(x2), MultiplyBy(3));
        std::for_each(x1.begin(), x1.end(), MultiplyBy(3));  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...