什么是std :: pair?

时间:2008-09-18 23:19:38

标签: c++ boost stl std-pair

什么是std::pair,我为什么要使用它,以及boost::compressed_pair带来哪些好处?

10 个答案:

答案 0 :(得分:81)

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<A, int>必须大于sizeof(int)

但是如果你使用compressed_pair,它生成的代码将类似于:

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

compressed_pair<A,int>只会和sizeof(int)一样大。

答案 1 :(得分:35)

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

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

另外,请查阅Pete Becker的书 The C ++标准库扩展:教程和参考第1章“Tuples”,ISBN-13:9780321412997,以获得详尽的解释。

alt text

答案 2 :(得分:11)

你有时需要从一个函数中返回2个值,并且为此创建一个类通常是过分的。

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

我认为boost:compressed_pa​​ir能够优化0大小的成员。 这对于图书馆中的重型模板机器来说非常有用。

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

答案 3 :(得分:11)

听到compressed_pa​​ir关心几个字节听起来很奇怪。但是当考虑可以使用compressed_pa​​ir的位置时,它实际上很重要。例如,让我们考虑一下这段代码:

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

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

boost::function鼓励其实现应用小对象优化。这意味着对于 small 仿函数,直接嵌入boost::function对象的小缓冲区用于存储仿函数。对于较大的仿函数,必须使用operator new来获取内存。在提升version 1.34之后,决定采用this optimization,因为有人认为可以获得一些非常好的性能优势。

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

所以,看起来只是浪费了很多想法,只有几个字节实际上会对性能产生重大影响。

答案 4 :(得分:3)

对于STL中的其他几个容器类,

std :: pair派上用场。

例如:

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

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

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

答案 5 :(得分:3)

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

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

答案 6 :(得分:3)

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

我更喜欢std :: pair用于任何“正常”使用,除非你进入沉重的模板元编程。

答案 7 :(得分:3)

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

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

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

答案 8 :(得分:2)

  

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

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

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

答案 9 :(得分:1)

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