我有一个带有自定义谓词的std::map<string, string>
:
struct PredIgnoreCase {
bool operator()(const std::string& str1, const std::string& str2) const {
std::string str1NoCase(str1), str2NoCase(str2);
std::transform(str1.begin(), str1.end(), str1NoCase.begin(), tolower);
std::transform(str2.begin(), str2.end(), str2NoCase.begin(), tolower);
return (str1NoCase < str2NoCase);
}
};
现在给予
typedef std::map<std::string, std::string> DIRECTORY_WITHCASE;
typedef std::map<std::string, std::string, PredIgnoreCase> DIRECTORY_NOCASE;
我初始化
// Case-sensitive directory: case of string-key plays no role
DIRECTORY_WITHCASE dirCaseSensitive{
make_pair("John", "2345764"),
make_pair("JOHN", "2345765"),
make_pair("Sara", "42367236"),
make_pair("Jack", "32435348"),
};
然后当我初始化时
DIRECTORY_NOCASE dirCaseInsensitive(dirCaseSensitive.begin(),
dirCaseSensitive.end());
dirCaseInsensitive
打印
Jack - >32435348
JOHN - >2345765 <---- John in upper case
Sara - >42367236
但是,如果我像这样初始化dirCaseInsensitive
:
DIRECTORY_NOCASE dirCaseInSensitive{
make_pair("John", "2345764"),
make_pair("JOHN", "2345765"),
make_pair("Sara", "42367236"),
make_pair("Jack", "32435348"),
};
它输出正确的地图:
Jack - >32435348
John - >2345764 <----- John in lower case
Sara - >42367236
为什么同一张图的不同构造函数会给出不同的结果?
答案 0 :(得分:4)
这里的订购很重要。如果您在make_pair("JOHN", "2345765")
结构中将make_pair("John", "2345764")
与dirCaseInSensitive
切换,您将看到第一个输出。
这里的情况是您第一次创建时:
DIRECTORY_WITHCASE dirCaseSensitive{
make_pair("John", "2345764"),
make_pair("JOHN", "2345765"),
make_pair("Sara", "42367236"),
make_pair("Jack", "32435348"),
};
由于键的排序,您的"JOHN"
键被放置为第一个键(在"John"
键之前)。现在,如果您尝试使用那个地图来初始化第二个地图,它将首先插入("JOHN", "2345765")
对,然后查看("John", "2345764")
对。它将不区分大小写地比较键并确定它们是等效的,因此不会插入小写的"John"
对。
因此,总而言之,它实际上不是构造函数的用法。这是您所提供的对的顺序和它们的键顺序(不匹配)的令人惊讶的组合。
答案 1 :(得分:2)
因为每种情况下的配对顺序都不同。在第一种情况下,dirCaseInsensitive
的构造函数(实际上)被按此顺序对进行调用。
make_pair("JOHN", "2345765"),
make_pair("Jack", "32435348"),
make_pair("John", "2345764"),
make_pair("Sara", "42367236"),
这是dirCaseSensitive
中的对的顺序(假设ASCII或类似字符集)。
在第二种情况下,dirCaseInsensitive
的构造函数按初始化程序列表指定的顺序成对调用。
make_pair("John", "2345764"),
make_pair("JOHN", "2345765"),
make_pair("Sara", "42367236"),
make_pair("Jack", "32435348"),
因此,您可以在第一种情况下看到“ JOHN”在“ John”之前,因此插入了“ JOHN”,但是在第二种情况下,情况正好相反。
答案 2 :(得分:1)
谓词仅定义元素的排序方式,但不修改元素。您偶然获得JOHN
和John
一次。在您的第一张地图中,JOHN
首先出现,因此当您使用
DIRECTORY_NOCASE dirCaseInsensitive(dirCaseSensitive.begin(),
dirCaseSensitive.end());
然后JOHN
将首先插入,然后John
被您的谓词视为等同。
如果您这样初始化它:
DIRECTORY_NOCASE dirCaseInSensitive{
make_pair("John", "2345764"),
make_pair("JOHN", "2345765"),
make_pair("Sara", "42367236"),
make_pair("Jack", "32435348"),
};
然后首先插入John
,因为JOHN
被视为同一键,因此不在映射中。
谓词不会修改元素(它们以const&
的形式传递),而只是控制先出现哪些元素以及哪些元素等效。如果您希望由于谓词而使用小写字母表示所有名称,那么这是错误的。如果仅插入大写字母名称,则地图将仅包含大写字母名称。
为说明这里发生的情况,请考虑一个映射,该映射在将数字作为键进行比较时会忽略最低有效数字。之后:
rounded_map[1] = "one";
rounded_map[4] = "four";
rounded_map[11] = "eleven";
然后,地图将包含值“ one”和“十一”,但是如果您交换订单
rounded_map[4] = "four";
rounded_map[1] = "one";
rounded_map[11] = "eleven";
您将获得“四个”和“十一”。