• STL std::pair基本用法


    std::pair 是一个结构体模板,其可于一个单元内存储两个相异对象。是 std::tuple 的拥有两个元素的特殊情况。

    一般来说,pair 可以封装任意类型的对象,可以生成各种不同的 std::pair<T1, T2> 对象,可以是数组对象或者包含 std::pair<T1,T2> 的 vector 容器。pair 还可以封装两个序列容器或两个序列容器的指针。

    1. 定义

    #include <utility>
    template<class T1, class T2> struct pair;

    模板参数 T1 和 T2 是 pair 所存储的元素的类型。

    包含有两个成员变量 first 和 second,而且都是 public 修饰的,通过 "." 访问。

    其中 first 类型为T1, second 类型为T2。

    • 1.1 成员函数
    (constructor)     constructs new pair (public member function)
    
    operator=        assigns the contents (public member function)
    
    swap             swaps the contents (public member function)
    • 1.2 非成员函数
    make_pair        creates a pair object of type, defined by the argument types (function template)
    
    operator==        lexicographically compares the values in the pair (function template)
    operator!=
    operator<
    operator<=
    operator>
    operator>=
    
    std::swap(std::pair)    specializes the std::swap algorithm (function template)
    
    std::get(std::pair)        accesses an element of a pair(function template)

    2. 初始化

    初始化一个 pair 可以使用构造函数,也可以使用 std::make_pair。

    make_pair 定义如下:

    template<class T1, class T2>
    std::pair make_pair(T1 a, T2 b) {
        return std::pair(a, b);
    }

    2.1 默认构造

    pair 有很多版本的引用参数,而且有一些版本的右值引用参数允许参数隐式转换为所需的类型。

    如下示例表示使用 4 种不同的方式来初始化 pair 对象:

    std::string s1 {"test”}, s2{"that"};
    std::pair<std::string, std::string> my_pair{s1, s2};
    
    std::pair<std::string, std::string> your_pair {std::string {"test"},std::string {"that"}};
    
    std::pair<std::string, std::string> his_pair {"test", std::string {"that"}};
    
    std::pair<std::string, std::string> her_pair {"test", "that"};

    第一个 pair 构造函数复制了所有参数的值。

    第二个移动参数值。

    第三个为了隐式转换而将第一个参数传给 string 的构造函数。

    最后一个构造函数将两个参数隐式转换为 string 对象而且它们会被移到 pair 的成员变量 first 和 second 中。

    由于这个构造函数有右值引用参数版本,因此任意一个或两个模板类型参数可以是 unique_ptr<T>。

    2.2 复制或移动构造

    pair 对象也可以复制或移动构造它的成员变量。例如:

    std::pair<std::string, std:: string> new_pair{my_pair}; // Copy constructor
    
    std::pair<std::string, std::string> old_pair{std::make_pair(std::string{"his"},std::string{"hers"})};

    old_pair 是由 pair<string,string> 类的移动构造函数生成的。

    2.3 复制或移动赋值

    不仅成员变量可以被复制和移动,pair 对象也支持复制和移动赋值。例如:

    std::pair<std::string, std::string> old_pair; // Default constructor
    
    std::pair<std::string, std::string> new_pair {std::string{"his"} , std::string{"hers"}};
    
    old_pair = new_pair; // Copy assignment
    
    new_pair = std::pair<std::string, std::string> {std::string{"these"}, std::string{"those"}}; // Move assignment

    默认的 pair 构造函数会用它的成员变量,即空的 string 对象来生成 old_pair 这是一个空的字符串对象。

    第 3 条语句一个成员一个成员地将 new_pair 复制到 old_pair 中。

    第 4 条语句将作为赋值运算符的右操作数的 pair 对象的成员变量移到 new_pair 中。

    2.4 不同类型成员变量隐式转换复制赋值

    当 pair 对象包含不同类型的成员变量时,也可以将一个 pair 对象赋值给另一个 pair 对象,只要作为右操作数的 pair 对象的成员变量可以隐式转换为左操作数的 pair 对象的成员变量的类型。

    例如:

    auto prl = std::make_pair ("these", "those"); // Type pair<const char*, const char*>
    
    std::pair<std::string, std::string> pr2; // Type pair<string, string>
    
    pr2 = prl; // OK in this case

    prl 成员变量 first 和 second 的类型是 const char*。这个类型可以隐式转换为 string,即 pr2 成员变量的类型,因此可以成功赋值。

    如果这些类型不能隐式转换,这条赋值语句就无法通过编译。

    示例

    #include <iostream>    // std::cout, std::endl
    #include <utility>     // std::pair, std::make_pair
    #include <string>    // std::string
     
    int main (int argc, char const* argv[]) {
        std::pair<std::string, double> product1 ("tomatoes", 3.25);    // value init
        std::pair<std::string, double> product2;
        std::pair<std::string, double> product3;                // default constructor
        std::pair<std::string, double> product4 (product1);        // copy constructor
         
        product2.first = "lightbulbs";            // the type of first is std::string
        product2.second = 0.99f;                // the type of second is double
         
        product3 = std::make_pair(std::string("shoes"), 20.0);        // using make_pair (move)
         
        std::cout << "The price of " << product1.first << " is $" << product1.second << std::endl; // The price of tomatoes is $3.25
        std::cout << "The price of " << product2.first << " is $" << product2.second << std::endl; // The price of lightbulbs is $0.99
        std::cout << "The price of " << product3.first << " is $" << product3.second << std::endl; // The price of shoes is $20
        std::cout << "The price of " << product4.first << " is $" << product4.second << std::endl; // The price of tomatoes is $3.25
    
        return 0;
    }

    3. 其他成员函数及非成员函数操作

    3.1 比较操作

    pair 对象支持全套的运算符 ==、 !=、 <、 <=、 >、 >=。

    当作为操作数的 pair 对象的类型相同并且其成员变量的比较方式也相同时,这些运算符都可以正常使用。

    std::pair<std::string, std::string> new_pair;
    
    new_pair.first = "his";
    
    new_pair.second = "hers";
    
    if (new_pair == std::pair<std::string, std::string> {"his", ,"hers"})
        std::cout << "the two pairs equal each other!
    ";

    new_pair 的成员变量 first 和 second 被赋值为右操作数所包含的字符串。

    当两个 pair 对象相等时,if 语句会输出一些消息。

    当两个 pair 对象中的任何一个或两个成员不相等时,!= 比较会返回 true。

    对于小于或大于比较,pair 对象的成员变量是按字典顺序比较的。

    如果 new_pair.first 小于 old_pair.first 的话,表达式 new_pair<old_pair 会返回 true。

    如果它们的成员变量 first 相等,但 new_pair.second 小于 old_pair.second,new_pair < old_pair 也为 true。

    下面是一个示例:

    std::pair<int, int> p1 {10, 9};
    
    std::pair<int, int> p2 {10, 11};
    
    std::pair<int, int> p3 {11, 9};
    
    std::cout<< (p1 < p2 ? "true" : "false") << "
    "
        << (p1 > p3 ? "true" : "false") << "
    "
        << (p3 > p2 ? "true" : "false") << std::endl;

    第一个比较的结果为 true,因为 p1 和 p2 的成员变量 first 相等,p1 的成员变量 second 小于 p2 的成员变量 second。

    第二个比较的结果为 false,因为 p1 的 first 小于 p3 的 first。

    第三个比较的结果则为 true,因为 p3 的 first 大于 p2 的 first。

    3.2 交换操作

    pair 的成员函数 swap() 可以和作为参数传入的另一个 pair 对象交换其成员变量 first 和 second。

    显然,参数必须是相同类型。下面有一个示例:

    std::pair<int, int> p1 {10, 11};
    
    std::pair<int, int> p2 {11, 9};
    
    p1.swap(p2); // p1={ll,9} p2={10/11}

    3.3 辅助函数

    make_pair<T1,T2> 函数模板是一个辅助函数,可以生成并返回一个 pair<T1,T2> 对象。

    auto my_pair = std::make_pair(s1, s2);
    
    auto your_pair = std::make_pair(std::string {"test"},std::string {"that"});
    
    auto his_pair = std::make_pair<std::string, std::string>("test",std::string {"that"});
    
    auto her_pair = std::make_pair<std::string, std::string>("test", "that");

    前两条语句中的函数模板的类型参数由编译器推断。

    在后两条语句中,类型是明确的。

    如果在这两条语句中忽略模板类型参数,那么对象类型将是 pair<const char*,string> 和 pair<const char*, const char*>。

    4. 应用

    结合map的简单使用

    std::pair m_pairA;
    m_pairA = std::make_pair("sn001", 12.5);
    
    std::map m_mapA;
    m_mapA.insert(m_pairA);
    std::map::iterator iter = m_mapA.begin();
    std::cout << iter->first << "," << iter->second << std::endl;

    参考资料

    [1] std::pair

    [2] C++ pair(STL pair)类模板的用法详解

    [3] Pair in C++ Standard Template Library (STL)

  • 相关阅读:
    牛客练习赛64 D.宝石装箱 【容斥原理+背包DP】
    洛谷 P5212 SubString【SAM+LCT】
    洛谷 P4219 [BJOI2014]大融合【LCT】
    洛谷 P1501 [国家集训队]Tree II【LCT】
    洛谷 P5357 【模板】AC自动机(二次加强版)
    洛谷 P3690 【模板】Link Cut Tree (动态树)
    洛谷 P2463 [SDOI2008]Sandy的卡片【后缀数组】
    P3181 [HAOI2016]找相同字符【后缀数组】
    洛谷 SP705 【后缀数组】
    牛客小白月赛18 E.Forsaken的数列【Splay】
  • 原文地址:https://www.cnblogs.com/phillee/p/12099504.html
Copyright © 2020-2023  润新知