什么是std :: pair?

时间:2020-03-06 14:23:59  来源:igfitidea点击:

std :: pair是什么意思,为什么要使用它,boost :: compressed_pa​​ir有什么好处?

解决方案

有时我们需要从一个函数中返回2个值,而仅仅为此创建一个类通常是过高的。

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

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

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

std :: pair在STL中的其他几个容器类中很方便。

例如:

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

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

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

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

boost :: compressed_pa​​ir声称效率更高:请参见此处

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

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

在学习" pair"时,我们可以签出" tuple"。就像" pair"一样,但是用于分组任意数量的值。 " tuple"是TR1的一部分,许多编译器已经将其包含在其标准库实现中。

另外,请查阅Pete Becker所著的《 C ++标准库扩展:教程和参考》一书的第1章" Tuples",以获取详尽的解释。

替代文字http://ak.buy.com/db_assets/prod_images/225/202452225.jpg

添加信息:当该对的类型之一为空结构时,boost :: compressed_pa​​ir很有用。当以编程方式从其他类型推断该对的类型时,通常在模板元编程中使用此方法。最后,我们通常会使用某种形式的"空结构"。

我更喜欢将std :: pair用于任何"常规"用途,除非我们要进行繁重的模板元编程。

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

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

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

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

所以即使你有

struct A { };

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

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

将举行,这是不允许的。

但是许多编译器会执行所谓的"空基类优化":

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

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

所以boost :: compressed_pa​​ir利用了这种优化,如果可能的话,将从对中的一种或者另一种类型继承。

因此,一个" std :: pair"可能看起来像(我已经大量淘汰了,ctor等):

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

这意味着,如果FirstType或者SecondType是A,则pair <A,int>必须大于sizeof(int)。

但是,如果我们使用" compressed_pa​​ir",则其生成的代码将类似于:

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

而" compressed_pa​​ir <A,int>"将仅与sizeof(int)一样大。

听到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个字节(对于成员函数来说并不罕见),而占位符只有1个字节(有关原因,请参见Logan的答案),那么对于绑定对象,我们可能需要9个字节。由于对齐,在通常的32位系统上,这可能会膨胀多达12个字节。

" boost :: function"鼓励其实现应用小对象优化。这意味着对于小函子,直接嵌入在`boost :: function'对象中的小缓冲区用于存储函子。对于较大的函子,必须使用new运算符来使用堆来获取内存。在Boost 1.34左右,决定采用此优化,因为它被认为可以获得一些非常大的性能优势。

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

因此,实际上仅浪费几个字节就浪费大量的思想实际上会对性能产生重大影响。

What is std::pair for, why would I use it?

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

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