関数 - stl c++ 使い方
マップ内のキーとしてのポインタC++ STL (4)
私はカスタムオブジェクトへのポインタがマップのキーとして使用されたときにどのように扱われるかについて質問をします。 より具体的には、私が定義すれば
std::map< CustomClass*, int > foo;
デフォルトのC ++実装がこれらのポインタを処理することはできますか? または、それを処理するカスタムコンパレータ関数を定義する必要がありますか? 一般に、オブジェクトへのポインタをキーとして使うのは良い習慣ですか?
C ++標準では、ポインタのためのstd::less
特殊化が提供されていましたので、マップキーなどとして安全に使用できます。
これの合法性や意味論的な誤解を除いて、 std::unordered_map
ではなく、 std::unordered_map
std::map
を使う理由は考えられません。 BoostとVisual C ++には、C ++ 11より前のコンパイラを使用している場合に、これの初期傍受があります。
一意のオブジェクトを表すためにポインタを使用しているように見えるので、 boost::flyweightようなものを適用することができます。
ポインタはキーとして使用できますが、特にstd :: map(またはstd :: set)を使用すると、私はそれを助言しません。 プログラムの振る舞いは決定的ではありません。つまり、マップを繰り返し処理すると、マップ内の項目が繰り返される順序は同じであることが保証されません 。 それは実際にオブジェクト(キー)のメモリアドレスに依存します。 この例を見てみましょう。マップへの挿入順序にかかわらず、キーがポインタではなく文字列である場合、アイテムは決定的な方法で反復されます。
#include <iostream>
#include <map>
using namespace std;
class SomeClass {
public:
SomeClass(const std::string& name): m_name(name) {}
std::string GetName()const {return m_name; }
bool operator <(const SomeClass& rhs) const { return m_name < rhs.m_name; }
private:
std::string m_name;
};
auto print_seq = [](const auto& seq) { for (const auto& itr: seq) {std::cout << itr.second << " , ";} std::cout << std::endl;};
int main() {
// your code goes here
std::map<SomeClass*, std::string> pointer_keyed_map;
SomeClass s3("object3");
SomeClass s1("object1");
SomeClass s2("object2");
pointer_keyed_map.insert(std::make_pair(&s1, s1.GetName()));
pointer_keyed_map.insert(std::make_pair(&s2, s2.GetName()));
pointer_keyed_map.insert(std::make_pair(&s3, s3.GetName()));
std::cout << "Pointer based keys: object order" << std::endl;
print_seq(pointer_keyed_map);
std::map<SomeClass, std::string> int_keyed_map;
int_keyed_map.insert(std::make_pair(s3, s3.GetName()));
int_keyed_map.insert(std::make_pair(s1, s1.GetName()));
int_keyed_map.insert(std::make_pair(s2, s2.GetName()));
std::cout << "String based keys: object order" << std::endl;
print_seq(int_keyed_map);
return 0;
}
ポインタは処理されますが、ポインタ(メモリの順序)として比較されます。 あなたはオブジェクトを比較したい場合、カスタムのless
ファンクタを渡す必要があります:
template<class T> struct ptr_less {
bool operator()(T* lhs, T* rhs) {
return *lhs < *rhs; }};
map<Object*,int,ptr_less<Object>> mymap;