#c #lambda #c 11
#c #лямбда #c 11
Вопрос:
У меня есть следующий код:
#include <iostream>
#include <vector>
#include <algorithm>
int main( int argc, char* argv[] )
{
std::vector< int > obj;
obj.push_back( 10 );
obj.push_back( 20 );
obj.push_back( 30 );
std::for_each( obj.begin(), obj.end(), []( int x )
{
return x 2;
} );
for( int amp;v : obj )
std::cout << v << " ";
std::cout << std::endl;
return 0;
}
Результат: 10, 20, 30
я хочу изменить все элементы в векторе (obj), используя лямбда-функции нового стандарта C 11.
Это код реализации for_each
функции:
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f)
{
for ( ; first!=last; first )
f(*first);
return f;
}
* изменено значение, переданное первым, и изменен код элемента, какую альтернативу for_each
я должен использовать, чтобы получить результат: 12, 22, 32?
Комментарии:
1. Вам нужно использовать lambda со ссылками. Я не знаю точного синтаксиса, но это было что-то вроде:
[amp;](int x){ ..}
2. @KirilKirov
amp;
Внутренняя часть[]
фиксирует окружающую среду (локальные переменные) по ссылке. Что ему нужно, так это просто ссылка на входной аргумент:[](int amp;x)
.3. @ChristianRau — спасибо. Я еще не изучал новый стандарт, я просто прочитал кое-что в википедии и не помню всего этого.
Ответ №1:
я хочу изменить все элементы в векторе (obj), используя лямбда-функции нового стандарта C 11.
Вы должны сделать это :
std::for_each( obj.begin(), obj.end(), [](int amp; x)
{ //^^^ take argument by reference
x = 2;
});
В вашем (не моем) коде возвращаемый тип лямбды выводится как int
, но возвращаемое значение игнорируется, поскольку его никто не использует. Вот почему в моем коде нет оператора return, а возвращаемый тип выводится как void
для этого кода.
Кстати, я нахожу for
цикл на основе диапазона менее подробным, чем std::for_each
для этой цели:
for( int amp;v : obj ) v = 2;
Комментарии:
1. Вы должны указать
return
в своем теле лямбда-выражения, должна ли функция возвращать что-либо.2. @wilhelmtell: Lambda ничего не возвращает.
Ответ №2:
Вам следует использовать transform
:
std::transform( obj.begin(), obj.end(), obj.begin(), []( int x )
{
return x 2;
} );
Комментарии:
1. Я думаю,
for_each
это так же ясно,transform
имеет больше смысла, когда вы используете пункт назначения, а не источник. В любом случае, если мы говорим «должны», я думаю, это то, что должно быть сделано:for(autoamp; x : obj) x = 2;
2. Я думаю, что оба
std::transform()
и цикл for на основе диапазона являются хорошим кодом здесь.std::transform()
говорит более семантически иfor
указывает меньше точек. Таким образом, вы можете утверждать в любом случае.
Ответ №3:
Передайте аргумент по ссылке и измените ссылку:
std::for_each( obj.begin(), obj.end(), [](int amp; x){ x = 2; } );
// ^^^^^
Ответ №4:
std::for_each( obj.begin(), obj.end(), []( intamp; x )
{
x = 2;
} );
Ответ №5:
В дополнение к уже существующим (и совершенно правильным) ответам, вы также можете использовать свою существующую лямбда-функцию, которая возвращает результат вместо изменения аргумента, и просто использовать std::transform
вместо std::for_each
:
std::transform(obj.begin(), obj.end(), obj.begin(), []( int x )
{
return x 2;
} );