什么是std::pair
,为什么我会使用它,以及boost::compressed_pair
带来什么好处?
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; };
在这里,它是罚款B
,并C
具有相同的尺寸,即使sizeof(A)
不能为零.
因此boost::compressed_pair
,利用此优化,并且如果可能的话,如果它是空的,则将继承该对中的一个或另一个类型.
所以std::pair
可能看起来像(我已经省略了很多,ctors等):
templatestruct pair { FirstType first; SecondType second; };
这意味着,如果任一FirstType
或者SecondType
是A
,你pair
必须比更大sizeof(int)
.
但是如果你使用compressed_pair
,它生成的代码将类似于:
struct compressed_pair : private A { int second_; A first() { return *this; } int second() { return second_; } };
并且compressed_pair
只会与sizeof(int)一样大.
std::pair
是一种数据类型,用于将两个值组合在一起作为单个对象. std::map
将它用于键值对.
在你学习的同时pair
,你可能会看看tuple
.它就像pair
分组任意数量的值一样. tuple
是TR1的一部分,许多编译器已将其与标准库实现包含在内.
另外,请查阅" C++标准库扩展: Pete Becker的教程和参考 "一书中的第1章"元组" ,ISBN-13:9780321412997,以获得详尽的解释.
有时你需要从一个函数中返回2个值,并且为此创建一个类通常是过度的.
std:pair在这些情况下派上用场.
我认为boost:compressed_pair能够优化大小为0的成员.这对于库中的重模板机制来说非常有用.
如果你直接控制类型,那就无关紧要了.
听到compressed_pair关心几个字节听起来很奇怪.但是当考虑可以使用compressed_pair的位置时,它实际上很重要.例如,让我们考虑一下这段代码:
boost::functionf(boost::bind(&f, _1));
在上述情况下使用compressed_pair会突然产生很大的影响.如果boost :: bind将函数指针和占位符存储_1
为成员本身或std::pair
本身存在,会发生什么?好吧,它可能会膨胀sizeof(&f) + sizeof(_1)
.假设函数指针有8个字节(对于成员函数来说并不罕见)并且占位符有一个字节(请参阅Logan的答案原因),那么我们可能需要9个字节用于绑定对象.由于对齐,在通常的32位系统上,这可能会膨胀到12个字节.
boost::function
鼓励其实现应用小对象优化.这意味着对于小型仿函数,直接嵌入boost::function
对象中的小缓冲区用于存储仿函数.对于较大的仿函数,必须使用operator new来获取内存.在升级版本1.34之后,决定采用这种优化,因为它被认为可以获得一些非常好的性能优势.
现在,这种小缓冲区的合理(但可能仍然非常小)限制将是8个字节.也就是说,我们非常简单的绑定对象不适合小缓冲区,并且需要存储new运算符.如果上面的绑定对象使用a compressed_pair
,它实际上可以将其大小减小到8个字节(或者经常是非成员函数指针的4个字节),因为占位符只不过是一个空对象.
因此,看起来只是浪费了很多想法,实际上只会对性能产生重大影响.