2016-11-13 1 views
-4
#include <iostream> 
using namespace std;  

struct ls{ 
bool operator()(int lhs, int rhs){ 
return lhs == rhs; 
}  
}; 

int main(){ 
map<int,string,ls> m1 {{1,"A"},{2,"B"}}; 
map<int,string>::iterator i; 

for(i=m1.begin();i!=m1.end();++i) { 
    cout<<i->first<<" - "<<i->second<<endl; 
}  

//If we print data here only 1, "A" data is present. 
     m1[2] = "C"; 
     for(i=m1.begin();i!=m1.end();++i) {  
     cout<<i->first<<" - "<<i->second<<endl; 
     } 

//the above statement updates m1[1] as "C" even though we are m1[2] 
} 
+3

[Unable](http://ideone.com/3Zgmc4)を再生する。ところで、カスタムの名前空間で 'operator()'を定義することによって(constメソッドでなければならず、const参照で引数を受け入れる必要があります)、 'std :: map'のテンプレートパラメータとして渡さないでください。 – Jack

+0

ジャック、あなたは両方のエントリを地図で見ることができますか?また、なぜconst refと引数としてメソッドをconstする必要がありますか? –

+0

@Jack:Constメソッド??なぜconst参照で 'int'を取るのですか? –

答えて

1

std::mapの比較関数であるべき第3のテンプレート引数の契約を尊重していないという問題があります。

デフォルトでstd::less<T>に設定されている比較機能は、std::mapのキーに合計発注を提供する必要があります。

フレーズ「キーの等価性は」比較していないキーのoperator==によって課される同値関係を意味します。この目的のためにISO規格では、§23.2.4.3で連想コンテナのために、定義されていることすなわち、​​とk2の2つのキーは、比較オブジェクトの場合には同等と見なされます。compcomp(k1, k2) == false & & comp(k2, k1) == false。同じコンテナにある​​とk2の2つのキーの場合、comp(k1, k2)を呼び出すときは常に同じ値を返します。あなたは

auto b1 = ls{}(1, 2); 
auto b2 = ls{}(2, 1}; 

ab未満とbない場合ので、両方のキーが一意のキー(と考えられている、両方のfalseであることを意味lhs == rhsとしての比較ではありません定義あなたの状況で今

a未満、abと等しくなければなりません)。これは、地図作成時に最初のペアのみが挿入されることを意味します。

m1[2] = "C"を使用すると、2にマップされた値への参照が取得され、2つの値が関数に応じて1と比較されるため、現在の唯一のキーを更新します。

+1

私は、このようなファンクタを指定すると、17.6.4.8のためUBになるという印象を受けました。だからコードが実際にやっているのはやや投機的ですが、それは実装があなたが記述したことを正確に行うことでしょう。 –

1

lsテンプレート引数が間違っています。 std::mapは、厳密な弱い注文を介して比較を実施する必要があります。 ISO C++標準の§23.2.4/ 2としては言う:

各連想コンテナはKeyKeyの 要素に厳密弱い順序(...)を誘発する注文 関係Compareにパラメータ化されます。

http://en.cppreference.com/w/cpp/concept/Compareも参照してください。とりわけ

が、これはすなわちX < X偽でなければならない、Xが自体よりも小さくすることはできませんを意味します。

あなたのlsファンクタは、まさしくそれを行います。 lhsが1で、rhsが1の場合、trueが返されます。これが間違っているという事実は驚くべきことではありません。実際には英語の表現が「何か他のものよりも小さい」ものを説明するための非常に技術的で正式な方法です。は実際には数学やコンピュータサイエンスという意味です。

いずれの場合でも、コードがstd::mapの要件を満たしていないため、プログラムにはの未定義の動作があります。


解決策は簡単です:lsを使用しないでください。 std::map<int, std::string>としてマップをインスタンス化してください。デフォルトの引数はstd::lessのインスタンスであるため、正しく動作します。

関連する問題