STL::pair

pair源码

pair类定义于通用工具<utility>头文件中。STL或者更广泛的说,C++标准库的这种文件组织方式,深刻地影响着软件设计结构。简单地说,也都有一个文件夹或者包或者模块,软件开发过程中可能用到的工具类或者方法,统一放在这些文件集合中。

当一个函数或者接口需要返回两个或者更多的值时,以及在一些情况下需要成对出现一些值时,pair便会是其中的一个选择,当然pair不限于两个数,也可实现pair的pair,pair也是一个模板类。

pair的源码其实非常简单:

// T1和T2可以是不同的类型
// T1和T2甚至都可以是pair模板
template<typename T1, typename T2>
struct pair
{
    typedef T1 first_type;
    typedef T2 second_type;
    // 为了让程序能够处理pair的两个值,
    // C++标准库使用struct进行封装(所有成员都是public),
    // 也即提供了“直接访问对应数据成员的能力”
    T1 first;
    T2 second;          // 两个成员变量
    pair():first(T1()), second(T2()){}
                    // pair<T1, T2> p;
                    // default构造函数,建立一个pair,
                    // 其元素类型分别为T1和T2,
                    // 各自以其default构造函数(T1(), T2())初始化
    pair(const T1& a, const T2& b) :first(a), second(b) {}
                    // pair<T1, T2> p(val1, val2);
                    // 以val1(T1类型),val2(T2类型)为初值进行初始化
}

pair的pair

比如我们要返回一个集合的一些统计数据,如最大值、最小值以及中位数,也就是我们需要一个刚好能够容纳三个数的容器

template<typename T, typename CONT>
::pair<T, ::pair<T, T>> stats(CONT& coll)
                    // ::域作用符是为了与库函数做区分
{
    std::sort(coll.begin(), coll.end());    
                    // 排序的目的是为了找到中位数
    auto minVal = *(coll.begin());
    auto maxVal = *(--coll.end());
    size_t  n = coll.size();
    auto median = (n%2 == 0) ? (coll[n/2] + coll[n/2-1])/2
                 : coll[n/2];
    return ::pair<T, ::pair<T, T>>(median, ::pair<T, T>(minVal, maxVal));
}

客户端程序:

int main(int, char**)
{
    std::vector<int> ivec{0, 1, 2, 3, 4};
    auto values = stats<int, vector<int>>(ivec);
    std::cout << "min: " << values.second.first 
              << "max: " << values.second.second 
              << "median: " << values.first << std::endl; 
    return 0;
}

pair与map容器的关系

map而言,所有元素都会根据元素的键值自动被排序,map的所有元素都是pair,同时拥有实值(value)和键值(key)。pair的第一个元素(first)被视为键值,第二个元素被视为实值(value),map不允许两个元素有相同的键值。

玩转pair

  • 让输出流适配pair类型数据
template<typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p)
{
    return os << "[" << p.first << ", " << p.second << "]" ;
}
  • 暂时忘却模板,便捷函数std::make_pair

显然这里的std::make_pair是一个模板函数,如此才可使用其便捷的自动类型推导。

// 由于之前的关于输出流的运算符重载
std::cout << std::pair<std::string, int>("InsideZhang", 23) << std::endl;

我们来看不显式使用模板的情况:

std::cout << std::make_pair("InsideZhang", 23) << std::endl;

有了自动类型推导(无模板而无不模板)更是让其如虎添翼:

auto p = std::make_pair("InsideZhang", 23);

根据客户端程序,我们可轻松给出它的内部实现:

template<typename T1, typename T2>
std::pair<T1, T2> make_pair(const T1& x, const T2& y)
{
    return std::pair<T1, T2>(x, y);
}

再来一个自动类型推导的版本:

template<typename T1, typename T2>
auto make_pair(const T1& x, const T2& y) -> decltype(std::pair<T1, T2>(x, y))
{
    return std::pair<T1, T2>(x, y);
}

你可能感兴趣的:(C++,map,STL,pair)