2つのstd::equal_to
を比較するためにstd::pair<std::string, unsigned>
を使用している次の簡単な例を考えてみます。 operator new
はオーバーロードされているため、割り当てが行われたときにメッセージが出力されます(ライブコード here ):
#include <functional>
#include <string>
#include <iostream>
// overloaded to see when heap allocations take place
void* operator new(std::size_t n)
{
std::cout << "Allocating " << n << std::endl;
return malloc(n);
}
int main()
{
using key_type = std::pair<std::string, unsigned>;
auto key1 = std::make_pair(std::string("a_______long______string______"), 1);
auto key2 = std::make_pair(std::string("a_______long______string______"), 1);
std::cout << "Finished initial allocations\n\n" << std::endl;
std::equal_to<key_type> eq;
eq(key1, key2); // how can this cause dynamic allocation???
}
私が見ているメッセージは
Allocating 31
Allocating 31
Finished initial allocations
Allocating 31
Allocating 31
key1
とkey2
を比較すると、2つの割り当てが行われていることがわかります。しかし、なぜ? std::equal_to
の演算子はconst参照によって引数を取得するため、割り当ては行われません...何が欠けていますか?ありがとう。
ペアのコピーを作成するためです。
keyX
のタイプはstd::pair<std::string, int>
です。 eq
には、引数const std::pair<std::string, unsigned>&, const std::pair<std::string, unsigned>&
の関数呼び出し演算子があります。型が一致しないため、参照を引数に直接バインドすることはできません。ただし、int
は暗黙的にunsigned
に変換できるため、指定されたペアは暗黙的に引数のペアに変換できます。
したがって、比較のために一時的な引数のペアを暗黙的に作成します。一時的な文字列を作成すると、メモリが割り当てられます。
std::equal_to<>
を比較演算子として使用した場合、引数の型を推定するため、コピーは作成されず、変換は行われません。