404 Not Found

404 Not Found


nginx

関数オブジェクトとラムダ式

[第]37[課では]iteratorについて学びました。

[今]、[私たちは]STLアルゴリズムの「[真髄]」――functionobject――を学びます。

アルゴリズム[は骨組み]であり、関数オブジェクト[は肉と血]である。[この両者が組み合わさって]初めて、STL[の真の威力を発揮]することができる。


1. functionobject[概要]

(1) 1.1 functionobjectとは何か?

関数オブジェクト(ファンクタ)[とは][関数][のように呼び出すことができる]オブジェクトのことである。

[3種類の]functionobject:

  1. 関数ポインタ
  2. functionobjectclass(オーバーロード operator()
  3. Lambda[式](C++11)

(2) 1.2 なぜ functionobject が必要なのか?

STLアルゴリズムは[はい][汎用的な]ものですが、[具体的な操作][は要件によって異なります]。functionobjectを使えば、[操作をカスタマイズ]することができます。

[生活]クラス[比]:



2. 関数ポインタ

基本的な使い方

例:[用]関数ポインタ[カスタムソート] (難易度 ⭐⭐)

▶ サンプル 2: STLコンテナ[使用] (難易度 ⭐)

CPP
#include iostream
#include vector
#include algorithm

// ...
bool compareDesc(int a, int b) {
 return a > b; // ...
}

int main() {
 std::vectorint v = {3, 1, 4, 1, 5, 9, 2, 6};
 
 // ...
 std::sort(v.begin(), v.end(), compareDesc);
 
 for (int x : v) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 return 0;
}
▶ 試してみよう

[実行結果]:

TEXT
9 6 5 4 3 2 2 1 1 

💡 ヒント:



3. 関数・オブジェクト・クラス

(1) 3.1 functionobjectclass とは何か?

functionobjectclass[は]オーバーロードされたoperator()[の]classであり、[その]インスタンスは[関数][のように呼び出すことができる]。

例:[カスタムコンパレータ] (難易度 ⭐⭐)

CPP
#include iostream
#include vector
#include algorithm
#include string

//:
struct CompareByLength {
 bool operator()(const std::string& a, const std::string& b) const {
 return a.length() < b.length();
 }
};

int main() {
 std::vectorstd::string words = {"apple", "banana", "cat", "dog"};
 
 // ...
 std::sort(words.begin(), words.end(), CompareByLength());
 
 for (const auto& w : words) {
 std::cout << w << " ";
 }
 std::cout << std::endl;
 
 return 0;
}

[実行結果]:

TEXT
cat dog apple banana 

(2) 3.2 functionobject[の利点]

[比較] 関数ポインタ 関数オブジェクトクラス
[状態] [状態なし] [状態あり](メンバー変数)
パフォーマンス [インライン化できない可能性がある] [インライン化可能]、[高速]
[柔軟性] [低] [高]([テンプレート化]可能)

(3) 3.3 [状態を持つ]functionobject

例:[カウンター]functionobject (難易度 ⭐⭐⭐)

CPP
#include iostream
#include algorithm
#include vector

//:
struct Counter {
 int threshold; // ()
 
 Counter(int t) : threshold(t) {}
 
 bool operator()(int x) const {
 return x > threshold; // threshold
 }
};

int main() {
 std::vectorint v = {1, 5, 10, 15, 20};
 
 //,10
 Counter counter(10);
 
 // 10
 int count = std::count_if(v.begin(), v.end(), counter);
 
 std::cout << "10:" << count << std::endl; // output:2
 
 return 0;
}


4. Lambda[式]

(1) 4.1 ラムダとは何か?

Lambda[式]は、C++11で導入された[匿名]関数であり、関数が必要な場所で直接定義することができます。

[基本構文]:

CPP
[capture](parameters) -> return_type { body }
[一部] [説明]
capture [キャプチャリスト]([外部キャプチャ]変数)
parameters [パラメータ一覧]
return_type [戻る]タイプ([省略可])
body 関数本体

(2) 4.2 [基本]例

例:Lambda[ソート] (難易度 ⭐)

CPP
#include iostream
#include vector
#include algorithm

int main() {
 std::vectorint v = {3, 1, 4, 1, 5, 9, 2, 6};
 
 // Lambda()
 std::sort(v.begin(), v.end(), (int a, int b) {
 return a > b;
 });
 
 for (int x : v) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 return 0;
}

(3) 4.3 [キャプチャリスト]

[キャプチャリスト][決定]Lambda[がアクセスできる外部]変数。

[取得方法] [説明]
`` [変数を一切取得しない]
[x] [按]value[捕獲]x
[&x] [参照] [キャプチャ] x
[=] [按]value[すべての変数を取得]
[&] [参照] [すべて取得] 変数
[this] [キャプチャ]thispointer([クラス内での]使用)

例:[状態を持つ]Lambda (難易度 ⭐⭐)

CPP
#include iostream
#include vector
#include algorithm

int main() {
 std::vectorint v = {1, 5, 10, 15, 20};
 int threshold = 10;
 
 // threshold
 int count = std::count_if(v.begin(), v.end(),
 [threshold](int x) {
 return x > threshold;
 });
 
 std::cout << "..." << threshold << ":" << count << std::endl;
 
 return 0;
}


5. STL[事前定義]functionobject

(1) 5.1 [算術]関数オブジェクト

functional ヘッダーファイルには、[よく使われる]関数オブジェクトが提供されています:

関数オブジェクト [機能]
std::plusT [加法] std::plusint()
std::minusT [減法] std::minusint()
std::multipliesT [乗法] std::multipliesint()
std::dividesT [除法] std::dividesint()
std::negateT [負の値] std::negateint()

例:[用]multiplies[倍増] (難易度 ⭐)

CPP
#include iostream
#include vector
#include algorithm
#include functional

int main() {
 std::vectorint v = {1, 2, 3, 4, 5};
 
 // ...
 std::transform(v.begin(), v.end(), v.begin(),
 std::bind(std::multipliesint(), std::placeholders::_1, 2));
 
 for (int x : v) {
 std::cout << x << " ";
 }
 std::cout << std::endl;
 
 return 0;
}

(2) 5.2 [比較]functionobject

関数オブジェクト [機能]
std::equal_toT [等于]
std::not_equal_toT [等しくない]
std::greaterT [大于]
std::lessT [小于]
std::greater_equalT [以上]
std::less_equalT [以下]

(3) 5.3 [論理]functionobject

関数オブジェクト [機能]
std::logical_andT [論理積]
std::logical_orT [論理和]
std::logical_notT [論理否定]


6. [総合]例

▶ サンプル 1: [成績処理プログラム] (難易度 ⭐⭐⭐)

CPP
#include iostream
#include vector
#include algorithm
#include functional

struct Student {
 std::string name;
 int score;
};

int main() {
 std::vectorStudent students = {
 {"...", 85},
 {"...", 92},
 {"...", 78}
 };
 
 // 1. bysorting
 std::sort(students.begin(), students.end(),
 (const Student& a, const Student& b) {
 return a.score > b.score;
 });
 
 // 2.
 auto max_it = std::max_element(students.begin(), students.end(),
 (const Student& a, const Student& b) {
 return a.score < b.score;
 });
 
 std::cout << "points:" << max_it->name << " " << max_it->score << std::endl;
 
 // 3.
 int passed = std::count_if(students.begin(), students.end(),
 (const Student& s) {
 return s.score >= 60;
 });
 
 std::cout << ":" << passed << std::endl;
 
 return 0;
}
▶ 試してみよう

❓ よくある質問

Q:ラムダ式と関数オブジェクト・クラス、どちらが良いですか? A:- [単純な処理] → ラムダ式(コードが簡潔) - [複雑な処理]/[再利用が必要な場合] → 関数オブジェクト・クラス(保守性が高い)


Q:auto [ラムダ型]を[導出]できますか? A:ラムダ型は[唯一の匿名]型であり、autoによる[導出]に[限定]され、[具体的な]型を[記述]することはできません。

CPP
auto func = (int x) { return x * 2; };
// std::function<int(int)> func = ... //,

Q:[いつ使うのか] std::function A:[functionobjectを][保存]する必要がある場合([メンバー変数として]、[戻り値として]など)、std::functionを使います。


📖 まとめ

[知識ポイント] [要点]
関数ポインタ [シンプルだが機能は限定的]
関数・オブジェクト・クラス [カスタマイズ可能な操作],[状態を持つことができる]
Lambda [匿名]関数,[簡潔かつ強力]
[事前定義]関数オブジェクト std::plus[など],functional[内]
[キャプチャリスト] Lambda[外部変数へのアクセス方法]

📝 練習問題

  1. **初心者(難易度 ⭐):[function(operator() をオーバーロードしたクラス)を模倣して作成し]、[「2つの整数の大きさを比較する」機能を実装し]、[std::sort を使ってテストする]。

  2. **中級(難易度 ⭐⭐):[std::function を使用して] 異なる型の呼び出し可能なオブジェクト([通常の]関数、ラムダ式、[擬似]関数)を[一元的に呼び出す]。

  3. **上級(難易度 ⭐⭐⭐):[std::bind を使用して] [一部の引数をバインドし]、[新しい呼び出し可能なオブジェクトを生成する]。[「引数の事前設定」] を行う [関数アダプタ] を実装する。



[次のレッスン]:STL[アダプタ](#39)

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%