C++ lambda 表示式與「函式物件」(functor)
- Created: 2024-06-27T16:29+08:00
- Published: 2024-11-17T17:01+08:00
- Categories: C-CPP
functor(Function Object)
首先要介紹的是 functor——一個過載了 operator()
的類,該類的例項可以使用 operator()
。
What are C++ functors and their uses? - Stack Overflow
stackoverflow 上的例子很好,改一下放在這裡:
struct add_x
{
add_x(int val) : x(val) {} // Constructor
int operator()(int y) const { return x + y; }
private:
int x;
};
struct output {
void operator()(const int & x) {
std::cout << x << " ";
}
};
int main()
{
vector<int> x{0, 1, 2, 3};
vector<int> y(x.size());
// Now you can use it like this:
add_x add_42(42); // create an instance of the functor class
int i = add_42(8); // and "call" it
std::cout << i << std::endl; // 50
// Pass a functor to std::transform, which calls the functor on every element
// in the input sequence, and stores the result to the output sequence
std::transform(x.begin(), x.end(), y.begin(), add_42); // y[i] = x[i] + 42
std::for_each(x.begin(), x.end(), output());
for (auto &i : y)
{
std::cout << i << " ";
}
return 0;
}
觀察下 std::for_each()
這類函式的函式簽名,最終只是呼叫了傳入引數的 ()
運算子,所以可以傳入一個 functor。
程式碼見 ./use-functor-lambda-to-sort.cpp
template <typename _InputIterator, typename _Function>
_GLIBCXX20_CONSTEXPR
_Function
for_each(_InputIterator __first, _InputIterator __last, _Function __f)
{
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_requires_valid_range(__first, __last);
for (; __first != __last; ++__first)
__f(*__first);
return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant.
}
只是簡單地將傳入引數 _f
作用於 element,對於 std::sort()
,其函式簽名為 sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
,也只是簡單地使用 __comp()
。所以只要傳入的物件支援 ()
運算就可以。
lambda
C++ 中 Lambda 表示式(匿名函式)與傳統的函式指標有什麼本質區別? - 雨樂的回答 - 知乎
lambda 實際上程式碼生成出了一個 functor,而 capture list 中的引數就是 functor 中的成員變數。
預設引用捕獲的成員變數是隻讀的,可以使用 mutable 來改變。
可以參考 C++ Insights - Iterator tests 看中間程式碼。
bool less_function(int const &a, int const &b)
{
return a < b;
}
struct Less
{
bool operator()(int const &a, int const &b) const
{
return a < b;
}
};
auto less_lambda = [](int const &a, int const &b)
{
return a < b;
};
Less less_functor{}; // an instance of less
int main()
{
vector<int> v = {1, 3, 5, 7, 2, 4, 6};
std::sort(v.begin(), v.end(), less_lambda);
std::sort(v.begin(), v.end(), less_function);
std::sort(v.begin(), v.end(), less_functor);
for (auto &i : v)
{
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
面試問題
使用 lambda 實現函式物件
讓介紹一下 C++ 裡的 lambda。給了
struct A {int x;}; std::vector<A> v;
,讓用std::sort
來排序:std::sort(v.begin(), v.end(), [](A &a, A &b) {return a.x < b.x;});
。
指出 lambda 是一種語法糖,要我把它用函式物件實現。我當時不太會函式物件。
問了這裡第三個引數 [](A &a, A &b) {return a.x < b.x;} 是什麼型別。問了 std::sort 的函式簽名是什麼。當時不會。參見 理解 STL —— 迭代器與函式物件。——鹹魚暄的程式碼空間
程式碼見 ./use-functor-lambda-to-sort.cpp