もくじ
やりたいこと
以前、久々に関数ポインタを触ったから復習をするという記事を書いたが、今どきのC++では関数ポインタなんてものは使わないらしい、、、ということを職場の人に聞いた。
代わりにstd::function
というものを使うらしい。
std::function
...聞いたこともない...となってしまったので、使い方を練習したい。
std::functionについて
C++11で実装された機能で、関数ポインタの代わりになる+それ以上に便利な機能があるらしい。
下に練習したときのコードを残しておく。
練習したときのコード
関数ポインタとstd::functionで使い心地の違いを比較するイメージで練習コードを書いた。
#include <iostream>
#include <functional>
// 実験用 普通の関数
int func(int val) { return val * 2; }
// 実験用クラス
class MyClass
{
public:
// 実験用 メンバ関数
int func(int val) { return val * 4; }
};
//--------------------
// メイン関数
int main()
{
///////////////
// 普通の関数
///////////////
// 関数ポインタ
int (*pfunc1A)(int) = func;
std::cout << pfunc1A(1) << std::endl;
// std::function
std::function<int(int)> pfunc1B = func;
std::cout << pfunc1B(2) << std::endl;
///////////////
// クラスのメンバ関数
// ※メンバ関数の場合は、
// ・メンバ関数へのポインタ
// ・クラスのインスタンスそのものorポインタ
// の合わせ技が必要。
///////////////
// 関数ポインタ
MyClass mycls; // ローカルインスタンスの場合(stack)
MyClass* pcls = new MyClass(); // newした場合(heap)
int (MyClass::*pfunc2A)(int) = &MyClass::func;// メンバ関数へのポインタ
std::cout << (mycls.*pfunc2A)(3) << std::endl;// stack
std::cout << (pcls->*pfunc2A)(3) << std::endl;// heap
// std::function
std::function<int(int)> pfunc2B = std::bind(&MyClass::func, &mycls, std::placeholders::_1);
std::cout << pfunc2B(4) << std::endl;
///////////////
// ラムダ
///////////////
// 関数ポインタ
int (*pfunc3A)(int) = [](int a) -> int { return a * 5; };
std::cout << pfunc3A(5) << std::endl;
// std::functioni
std::function<int(int)> pfunc3B = [](int a) -> int { return a * 6; };
std::cout << pfunc3B(6) << std::endl;
system("pause");
}
使った感じ
- 関数ポインタは、書いた感じ、どれが名前なのか?とか、なんかごちゃっとしててわかりづらい、という印象を受けてしまうが、std::functionは見た目もすっきりしていて書きやすいと感じた。
- メンバ関数を扱う場合の、関数ポインタとstd::functionのコード量の差が大きく、そういうところが便利なんだろうとは思った(が、そういう使い方をまだしたことがないので実感ナシ)
という感触だったので、見た目がすっきり、コード量減る、ということであれば使っていきたいと感じた。
参考
基本的な使い方がわかりやすかったページ
メンバ関数を扱うときの「合わせ技」の理解につながったページ
メンバ関数のアドレスの取り方を見たページ
bindって何?となったときに見たページ