sort
sort 是一个函数模板,当我们调用sort时,编译器可以通过函数实参来推断模板实参,所以我们通常不需要显式地定义模板实参。下述,a. 、 b. 和 c.实质上是一样的,a. 只是编译器帮我们推到了模板实参。
vector<int> v{ 1,2,3,4 };
sort(v.begin(), v.end(), less<int>()); //a.
sort<vector<int>::iterator, less<int>>(v.begin(), v.end(), less<int>()); //b.
sort<decltype(v.begin()), less<int>>(v.begin(), v.end(), less<int>()); //c.
从上图可以看到sort的第三个参数需要直接传入一个实例化的对象作为函数实参。
vector<int> v{ 1,2,3,4 };
sort(v.begin(), v.end(), less<int>()); //正确,()就是调用默认构造函数,实例化一个对象
sort(v.begin(), v.end(),less<int>); //错误,less<int>只是类型名,不是一个实例化的对象
priority_queue
priority_queue是类模板,与函数模板不同,编译器不能为类模板推断函数模板参数类型,因此,当我们使用不是默认类模板参数时,需要传入模板参数。priority_queue的第三个参数是模板参数。
vector<int> v{ 1, 2, 3, 4};
priority_queue<int, vector<int>, less<int>> pq; //正确,传入类型名
priority_queue<int, vector<int>, less<int>()> pq1; //错误,出入对象
那么为什么传入第三个参数时有时候需要 pq(cmp),有时候又不需要?
从源码可以看出,当传入 pq(cmp)时,会用cmp初始化 comp比较算子,未传入时,则调用默认构造函数初始话comp比较算子。因为lambda函数不存在,所以需要传入 pq(cmp)。a. 和 b. 一样,只是decltype可以自动推导表达式的类型。
vector<int> v{ 1, 2, 3, 4};
auto cmp = [](int left, int right) {return left < right; };
priority_queue<int, vector<int>, decltype(cmp)> pq(cmp); // a.
priority_queue<int, vector<int>, function<bool(int, int)>> pq(cmp); // b.
当使用仿函数时,struct 存在默认构造函数,所以传不传入pq(cmp)都可以。
vector<int> v{ 1, 2, 3, 4};
struct cmp
{
bool operator()(int left, int right)
{
return left < right;
}
};
priority_queue<int, vector<int>, cmp> pq;
priority_queue<int, vector<int>, cmp> pq(cmp);
若将默认构造函数删除(下c.),则 , d不能通过编译, e 能
vector<int> v{ 1, 2, 3, 4};
struct cmp
{
cmp() = delete; //c.
bool operator()(int left, int right)
{
return left < right;
}
};
priority_queue<int, vector<int>, cmp> pq; //d.
priority_queue<int, vector<int>, cmp> pq(cmp); //e.
总结
- sort 的第三个参数传入的时对象
- priority_queue第三个传入的是模板参数