2016-03-29 6 views
1

В настоящее время я не могу окутать голову. Я ожидал выхода, где каждый элемент увеличивался на 1. Очевидно, что это не так.bind2nd в цикле for_each

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

Я считаю, что это правильно? Может ли кто-нибудь подтвердить или предоставить правильное объяснение, что контейнер не будет изменен?

#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <functional> using namespace std; void printer(int i) { 
     cout << i << ", "; } int main() { 
     int mynumbers[] = { 8, 9, 7, 6, 4, 1 }; 
     vector<int> v1(mynumbers, mynumbers + 6); 
     for_each(v1.begin(), v1.end(), bind2nd(plus<int>(), 1));//LINE I 
     for_each(v1.rbegin(), v1.rend(), printer);//LINE II 
     return 0; } 

ответ

1
for_each(v1.begin(), v1.end(), bind2nd(plus<int>(), 1)); 

эквивалентна как:

for (auto first = v1.begin(); first != last; ++first) { 
    plus<int>()(*first, 1); // i.e. *first + 1; 
} 

Как вы видели это ничего не изменит.

Вы можете использовать функтор, который изменит значение с std::for_each:

std::for_each(v1.begin(), v1.end(), [](int &n){ n += 1; }); 
1

std::for_each не изменяет входную последовательность.

Чтобы применить изменения к каждому элементу контейнера, используйте std::transform вместо:

transform(v1.begin(), v1.end(), v1.begin(), bind2nd(plus<int>(), 1)); 
//        ~~~~~~~~~^ puts the results back into the input sequence 
2

Декларация operator() из template <typename T> std::plus является

T operator()(const T& lhs, const T& rhs) const; 

т.е. она не изменяет входные аргументы. Вам нужно std::transform:

std::transform(v1.cbegin(), v1.cend() v1.begin(), std::bind2nd(std::plus<int>(), 1)); 

или вы можете использовать лямбда, который делает изменить это входной аргумент:

std::for_each(v1.begin(), v1.end(), [] (int& x) { ++x; });