【问题标题】:What is std::pair?什么是 std::pair?
【发布时间】:2010-09-11 00:12:23
【问题描述】:

std::pair 是做什么用的,我为什么要使用它,boost::compressed_pair 带来什么好处?

【问题讨论】:

    标签: c++ boost stl std-pair


    【解决方案1】:

    compressed_pair 使用一些模板技巧来节省空间。在 C++ 中,一个对象(小 o)不能与不同的对象具有相同的地址。

    所以即使你有

    struct A { };
    

    A 的大小不会为 0,因为这样:

    A a1;
    A a2;
    &a1 == &a2;
    

    会保持,这是不允许的。

    但是很多编译器会做所谓的“空基类优化”:

    struct A { };
    struct B { int x; };
    struct C : public A { int x; };
    

    在这里,BC 的大小可以相同,即使 sizeof(A) 不能为零。

    所以boost::compressed_pair 利用了这种优化,如果可能,如果它是空的,它将继承自该对中的一个或另一个类型。

    所以std::pair 可能看起来像(我已经省略了很多,ctors 等):

    template<typename FirstType, typename SecondType>
    struct pair {
       FirstType first;
       SecondType second;
    };
    

    这意味着如果FirstTypeSecondTypeA,您的pair&lt;A, int&gt; 必须大于sizeof(int)

    但如果您使用compressed_pair,其生成的代码将类似于:

     struct compressed_pair<A,int> : private A {
        int second_;
        A first() { return *this; }
        int second() { return second_; }
     };
    

    compressed_pair&lt;A,int&gt; 只会和 sizeof(int) 一样大。

    【讨论】:

    • 刚读到这个想法,该死的这家伙的答案是经过深思熟虑和完整的,然后才意识到是谁,甚至没有半点惊讶!嘿洛根!
    • 我错过了什么重要的事情吗?请告诉我,这个人是谁?我也想表扬他:)
    • 据我所知,我没有两个人。嗨,多姆! :)
    • 另外,我想补充一点,compressed_pa​​ir 是完全没用的,除非你正在做一些繁重的泛型编程,因为没有(我的意思是)你放置类的真实情况没有一对数据。
    • @ViktorSehr 似乎对于存储智能指针类的自定义删除器/克隆器很有用。一般来说,类中不会有任何数据成员,但仍然需要支持有状态的分配器/释放器。这就是我在这里所期待的。我不认为这是“繁重”的泛型编程。
    【解决方案2】:

    std::pair 是一种用于将两个值组合为一个对象的数据类型。 std::map 将其用于键值对。

    在学习pair 时,您可以查看tuple。这就像pair,但用于对任意数量的值进行分组。 tuple 是 TR1 的一部分,许多编译器已经将它包含在他们的标准库实现中。

    另外,请查看 Pete Becker 所著的C++ 标准库扩展:教程和参考一书的第 1 章“元组”,ISBN-13:9780321412997,以获得详尽的解释。 p>

    【讨论】:

    • 另外,如果你的编译器还不支持 TR1,boost 库有一个很好的元组实现。
    【解决方案3】:

    您有时需要从一个函数中返回 2 个值,而为此创建一个类通常是多余的。

    std:pair 在这些情况下会派上用场。

    我认为 boost:compressed_pa​​ir 能够优化掉大小为 0 的成员。 这对于库中的重型模板机制最有用。

    如果您确实直接控制类型,则无关紧要。

    【讨论】:

    • 您可以使用 boost::tie 来编写近似于“a,b​​ = func();”的代码。您无需显式实例化一对,而是编写:“boost::tie(a,b) = func();”。
    【解决方案4】:

    听到compressed_pa​​ir 关心几个字节听起来很奇怪。但是当考虑可以在哪里使用压缩对时,它实际上可能很重要。例如,让我们考虑以下代码:

    boost::function<void(int)> f(boost::bind(&f, _1));
    

    在上述情况下使用compressed_pa​​ir 可能会突然产生重大影响。如果 boost::bind 将函数指针和占位符 _1 本身存储为成员或存储在 std::pair 中,会发生什么情况?好吧,它可能会膨胀到sizeof(&amp;f) + sizeof(_1)。假设函数指针有 8 个字节(对于成员函数来说并不少见),而占位符有一个字节(请参阅 Logan 的回答了解原因),那么我们可能需要 9 个字节用于绑定对象。由于对齐,这可能会在通常的 32 位系统上膨胀多达 12 个字节。

    boost::function 鼓励其实现应用小对象优化。这意味着对于 small 函子,直接嵌入在boost::function 对象中的小缓冲区用于存储函子。对于较大的函子,必须通过使用 operator new 来使用堆来获取内存。围绕 boost version 1.34,决定采用this optimization,因为它被认为可以获得一些非常好的性能优势。

    现在,这样一个小缓冲区的合理限制(但可能仍然很小)是 8 个字节。也就是说,我们非常简单的绑定对象 适合小缓冲区,并且需要存储 operator new。如果上面的绑定对象使用compressed_pair,它实际上可以将其大小减少到8 个字节(对于非成员函数指针,通常为4 个字节),因为占位符只不过是一个空对象。

    因此,看起来只是为了几个字节而浪费大量精力实际上会对性能产生重大影响。

    【讨论】:

      【解决方案5】:

      它是存储一对值的标准类。它被一些标准函数返回/使用,例如std::map::insert

      boost::compressed_pair声称效率更高:see here

      【讨论】:

        【解决方案6】:

        std::pair 对于 STL 中的其他几个容器类非常有用。

        例如:

        std::map<>
        std::multimap<> 
        

        两者都存储 std::pairs 键和值。

        在使用地图和多重地图时,您经常使用指向一对的指针来访问元素。

        【讨论】:

          【解决方案7】:

          附加信息:当对的类型之一是空结构时, boost::compressed_pa​​ir 很有用。当对的类型以编程方式从其他类型推断时,这通常用于模板元编程中。最后,你通常会有某种形式的“空结构”。

          我更喜欢 std::pair 用于任何“正常”使用,除非您从事繁重的模板元编程。

          【讨论】:

            【解决方案8】:

            它只不过是一个具有两个变量的结构。

            我实际上不喜欢使用 std::pair 来返回函数。代码的读者必须知道 .first 是什么以及 .second 是什么。

            我有时使用的折衷方案是立即创建对 .first 和 .second 的常量引用,同时清楚地命名引用。

            【讨论】:

            • 我同意你的命名约定。使维护更加困难。
            【解决方案9】:

            std::pair 有什么用,我为什么要使用它?

            它就像简单的两个元素元组一样。它是在STL 的第一个版本中定义的,当时编译器还没有广泛支持模板和元编程技术,而这些技术需要实现更复杂的元组类型,例如Boost.Tuple

            它在许多情况下都很有用。 std::pair 用于标准关联容器。它可以用作范围std::pair&lt;iterator, iterator&gt; 的一种简单形式 - 因此可以定义接受单个对象表示范围的算法,而不是分别接受两个迭代器。 (在许多情况下它是一个有用的替代方案。)

            【讨论】:

              【解决方案10】:

              有时,您总是一起传递两条信息,无论是作为参数,还是作为返回值,或其他。当然,您可以编写自己的对象,但如果它只是两个小的原语或类似的,有时一对似乎就好了。

              【讨论】:

                猜你喜欢
                • 2023-03-28
                • 2015-01-07
                • 2012-03-05
                • 2012-11-24
                • 1970-01-01
                • 1970-01-01
                • 2011-03-24
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多