现代C++7-容器汇编II:需要函数对象的容器

上一讲我们学习了 C++ 的序列容器和两个容器适配器,今天我们继续讲完剩下的标准容器([1])。

函数对象及其特化

在讲容器之前,我们需要首先来讨论一下两个重要的函数对象,less 和 hash。

我们先看一下 less,小于关系。在标准库里,通用的 less 大致是这样定义的:

template <class T>

struct less

: binary_function<T, T, bool> {

bool operator()(const T& x,

const T& y) const

{

return x < y;

}

};

也就是说,less 是一个函数对象,并且是个二元函数,执行对任意类型的值的比较,返回布尔类型。作为函数对象,它定义了函数调用运算符(operator()),并且缺省行为是对指定类型的对象进行 < 的比较操作。

有点平淡无奇,是吧?原因是因为这个缺省实现在大部分情况下已经够用,我们不太需要去碰它。在需要大小比较的场合,C++ 通常默认会使用 less,包括我们今天会讲到的若干容器和排序算法 sort。如果我们需要产生相反的顺序的话,则可以使用 greater,大于关系。

计算哈希值的函数对象 hash 就不一样了。它的目的是把一个某种类型的值转换成一个无符号整数哈希值,类型为 size_t。它没有一个可用的默认实现。对于常用的类型,系统提供了需要的特化 [2],类似于:

template <class T> struct hash;

template <>

struct hash<int>

: public unary_function<int, size_t> {

size_t operator()(int v) const

noexcept

{

return static_cast<size_t>(v);

}

};

这当然是一个极其简单的例子。更复杂的类型,如指针或者 string 的特化,都会更复杂。要点是,对于每个类,类的作者都可以提供 hash 的特化,使得对于不同的对象值,函数调用运算符都能得到尽可能均匀分布的不同数值。

我们用下面这个例子来加深一下理解:

#include <algorithm> // std::sort

#include <functional> // std::less/greater/hash

#include <iostream> // std::cout/endl

#include <string> // std::string

#include <vector> // std::vector

#include "output_container.h"

using namespace std;

int main()

{

// 初始数组

vector<int> v{13, 6, 4, 11, 29};

cout << v << endl;

// 从小到大排序

sort(v.begin(), v.end());

cout << v << endl;

// 从大到小排序

sort(v.begin(), v.end(),

greater<int>());

cout << v << endl;

cout << hex;

auto hp = hash<int*>();

cout << "hash(nullptr) = "

<< hp(nullptr) << endl;

cout << "hash(v.data()) = "

<< hp(v.data()) << endl;

cout << "v.data() = "

<< static_cast<void*>(v.data())

<< endl;

auto hs = hash<string>();

cout << "hash(\"hello\") = "

<< hs(string("hello")) << endl;

cout << "hash(\"hellp\") = "

<< hs(string("hellp")) << endl;

}

在 MSVC 下的某次运行结果如下所示:

{ 13, 6, 4, 11, 29 }

{ 4, 6, 11, 13, 29 }

{ 29, 13, 11, 6, 4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员zhi路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值