【发布时间】:2010-09-11 00:12:23
【问题描述】:
std::pair 是做什么用的,我为什么要使用它,boost::compressed_pair 带来什么好处?
【问题讨论】:
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 等):
template<typename FirstType, typename SecondType>
struct pair {
FirstType first;
SecondType second;
};
这意味着如果FirstType 或SecondType 是A,您的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) 一样大。
【讨论】:
您有时需要从一个函数中返回 2 个值,而为此创建一个类通常是多余的。
std:pair 在这些情况下会派上用场。
我认为 boost:compressed_pair 能够优化掉大小为 0 的成员。 这对于库中的重型模板机制最有用。
如果您确实直接控制类型,则无关紧要。
【讨论】:
听到compressed_pair 关心几个字节听起来很奇怪。但是当考虑可以在哪里使用压缩对时,它实际上可能很重要。例如,让我们考虑以下代码:
boost::function<void(int)> f(boost::bind(&f, _1));
在上述情况下使用compressed_pair 可能会突然产生重大影响。如果 boost::bind 将函数指针和占位符 _1 本身存储为成员或存储在 std::pair 中,会发生什么情况?好吧,它可能会膨胀到sizeof(&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 个字节),因为占位符只不过是一个空对象。
因此,看起来只是为了几个字节而浪费大量精力实际上会对性能产生重大影响。
【讨论】:
它是存储一对值的标准类。它被一些标准函数返回/使用,例如std::map::insert。
boost::compressed_pair声称效率更高:see here
【讨论】:
std::pair 对于 STL 中的其他几个容器类非常有用。
例如:
std::map<>
std::multimap<>
两者都存储 std::pairs 键和值。
在使用地图和多重地图时,您经常使用指向一对的指针来访问元素。
【讨论】:
附加信息:当对的类型之一是空结构时, boost::compressed_pair 很有用。当对的类型以编程方式从其他类型推断时,这通常用于模板元编程中。最后,你通常会有某种形式的“空结构”。
我更喜欢 std::pair 用于任何“正常”使用,除非您从事繁重的模板元编程。
【讨论】:
它只不过是一个具有两个变量的结构。
我实际上不喜欢使用 std::pair 来返回函数。代码的读者必须知道 .first 是什么以及 .second 是什么。
我有时使用的折衷方案是立即创建对 .first 和 .second 的常量引用,同时清楚地命名引用。
【讨论】:
std::pair 有什么用,我为什么要使用它?
它就像简单的两个元素元组一样。它是在STL 的第一个版本中定义的,当时编译器还没有广泛支持模板和元编程技术,而这些技术需要实现更复杂的元组类型,例如Boost.Tuple。
它在许多情况下都很有用。 std::pair 用于标准关联容器。它可以用作范围std::pair<iterator, iterator> 的一种简单形式 - 因此可以定义接受单个对象表示范围的算法,而不是分别接受两个迭代器。
(在许多情况下它是一个有用的替代方案。)
【讨论】:
有时,您总是一起传递两条信息,无论是作为参数,还是作为返回值,或其他。当然,您可以编写自己的对象,但如果它只是两个小的原语或类似的,有时一对似乎就好了。
【讨论】: