導入
皆さんは、std::mapやstd::setで検索を行う際、検索対象の型とキーの型が異なると「一時オブジェクト」が生成されていることを意識したことはありますか?例えばstd::stringをキーにしたマップに対して、文字列リテラル(const char)でfindメソッドを呼ぶと、内部で一度std::stringへの変換が発生します。これはヒープメモリの確保を伴うため、パフォーマンスへの悪影響を及ぼします。C++14で導入された「透過的コンパレータ(Transparent Comparators)」は、この無駄な変換コストをゼロにするための重要な最適化手法です。
基礎知識
通常、std::mapやstd::setは、テンプレート引数として比較関数オブジェクト(デフォルトではstd::less)を受け取ります。C++14以前のstd::lessは、引数としてT型のオブジェクトを要求していました。そのため、異なる型で検索をかけると、型変換が強制されていました。
透過的コンパレータとは、比較関数内の演算子(operator())がテンプレート化されており、異なる型同士の比較を直接受け入れられるものを指します。標準ライブラリでは、std::less<>(<>の中に型を指定しない)がこれに該当し、コンテナの検索処理を最適化します。
実装/解決策
解決策は非常にシンプルです。std::mapやstd::setを宣言する際、第三テンプレート引数にstd::less<>を指定するだけです。これにより、コンテナは「型変換を行わずに比較する」という挙動に切り替わります。特に、std::string_viewやconst charを頻繁に検索キーとして使用する場合、この変更だけで検索時のメモリ確保(ヒープアロケーション)を完全に排除できます。
サンプルプログラム
以下のコードは、std::less<>を使用することで、std::string型のマップに対して文字列リテラルで効率的に検索を行う例です。
include
include
コメント