为什么在声明std :: set时需要重复排序子程序?

EMi*_*ler 6 c++ dictionary stl set c++11

在我的C++程序中,我试图按值而不是按键对我的地图进行排序.

这个问题来看,似乎很清楚,这样做的方法是创建一个集合,其元素是成对的,并且由我自己的less-than函数排序.

这是一些示例代码,我尝试这样做:

#include <map>
#include <set>
#include <iostream>
#include <string>

using namespace std;

bool compareCounts(const pair<string, size_t> &lhs, const pair<string, size_t> &rhs);

int main (int argc, char *argv[]) {
        map <string, size_t> counter = { {"A", 1}, {"B", 2}, {"C", 3} };
        set <pair<string, size_t>, decltype(compareCounts) *> sorted_counter;
        for (map<string, size_t>::iterator it = counter.begin(); it != counter.end(); ++it) {
                cout << "About to add: " << it->first << ":" << it->second << endl;
                auto ret = sorted_counter.insert(*it);
                if (! ret.second) {
                        cout << "ERROR adding this element!" << endl;
                } else {
                        cout << "Element added ok" << endl;
                }
                cout << "Set is of size: " << sorted_counter.size() << endl;
        }

        return 0;
}

bool compareCounts(const pair<string, size_t> &lhs, const pair<string, size_t> &rhs) {
        return lhs.second > rhs.second;
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

即将添加:A:1
元素添加确定
设置大小:1
关于添加:B:2
分段故障:11

我注意到当我去添加第二个元素时,事情就崩溃了.我发现这种情况正在发生,因为现在需要调用我的排序子程序compareCounts.

解决方法是更改​​此行:

set <pair<string, size_t>, decltype(compareCounts) *> sorted_counter;
Run Code Online (Sandbox Code Playgroud)

对此:

set <pair<string, size_t>, decltype(compareCounts) *> sorted_counter(compareCounts);
Run Code Online (Sandbox Code Playgroud)

为什么我需要指定compareCounts两次排序子程序?编译器是否已经从我的类型定义中知道了它?

Pra*_*ian 6

set <pair<string, size_t>, decltype(compareCounts) *> sorted_counter;
Run Code Online (Sandbox Code Playgroud)

你从未指定set实际使用的比较器.将上面的行更改为

set <pair<string, size_t>, decltype(compareCounts) *> sorted_counter(compareCounts);
Run Code Online (Sandbox Code Playgroud)

如果没有指定比较器,set默认构造one(nullptr),当它尝试使用比较器插入第二个元素时,代码崩溃.

您应该只使用函子而不是函数指针

struct compareCounts
{
    bool operator()(const pair<string, size_t> &lhs, 
                    const pair<string, size_t> &rhs) const
    {
        return lhs.second > rhs.second;
    }
};

set <pair<string, size_t>, compareCounts> sorted_counter;
Run Code Online (Sandbox Code Playgroud)

  • @ User7391即你告诉它比较器的*type*,但实际上从来没有*给它一个. (2认同)
  • @David怎么样`auto comp = [](...){return ...;}; std :: set <foo,decltype(comp)> s(comp);`?(我仍然喜欢仿函数版本) (2认同)