有如下代码:
std::set<std::string*> datas;
datas.insert(new std::string("Anteater"));
datas.insert(new std::string("Wombat"));
datas.insert(new std::string("Lemur"));
datas.insert(new std::string("Penguin"));
打印datas中的内容:
for (auto* pData : datas)
{
std::cout << *pData << std::endl;
}
希望输出的内容是按照字母顺序排序,然后却并非如此。
原因如下:
类型std::set<std::string*>,补全后其实际的类型为:
std::set<std::string*, std::less<std::string*>, std::allocator<std::string*>>。
这里,排序准则是std::less<std::string*>而非希望的按照字母顺序排序的准则std::less<std::string>,它将按照std::string*的指针值进行排序,而不是std::string的值进行排序。
如果想让std::string*数据在std::set中按照字母顺序排序,必须编写自己的排序准则。排序准则用在序列容器的定义中时,语法要求其必须是个类型,不能是普通函数需要使用函数对象(函数子)。C++11中引入了Lambda表达式,它的返回值就是函数对象。
最新的类型声明为:
auto sortFunc = [](const std::string* pLeft, const std::string* pRight) {return *pLeft < *pRight; };
std::set<std::string*, sortFunc> datas;
...
每当你要创建包含指针的关联容器时,一定要记住,容器将会按照指针的值进行排序。绝大多数情况下,这不会是你所希望的,所以你几乎肯定要创建自己的函数对象作为该容器的比较函数。