什么是 std::pair?

发布于 2024-07-05 10:22:43 字数 90 浏览 5 评论 0原文

std::pair 是什么,为什么要使用它,以及 boost::compressed_pa​​ir 带来什么好处?

What is std::pair for, why would I use it, and what benefits does boost::compressed_pair bring?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

成熟稳重的好男人 2024-07-12 10:22:43

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

所以即使你有

struct A { };

A 的大小也不会是 0,因为 then:

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

会成立,这是不允许的。

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

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

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

因此,boost::compressed_pa​​ir 利用了这种优化,并且在可能的情况下,从该对中的一个或另一个类型(如果该类型为空)继承。

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

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

这意味着如果 FirstTypeSecondTypeA,您的 pair 必须大于 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 将仅与 sizeof(int) 一样大。

compressed_pair uses some template trickery to save space. In C++, an object (small o) can not have the same address as a different object.

So even if you have

struct A { };

A's size will not be 0, because then:

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

would hold, which is not allowed.

But many compilers will do what is called the "empty base class optimization":

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

Here, it is fine for B and C to have the same size, even if sizeof(A) can't be zero.

So boost::compressed_pair takes advantage of this optimization and will, where possible, inherit from one or the other of the types in the pair if it is empty.

So a std::pair might look like (I've elided a good deal, ctors etc.):

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

That means if either FirstType or SecondType is A, your pair<A, int> has to be bigger than sizeof(int).

But if you use compressed_pair, its generated code will look akin to:

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

And compressed_pair<A,int> will only be as big as sizeof(int).

江城子 2024-07-12 10:22:43

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

当您学习 pair 时,您可能查看元组。 它类似于pair,但用于对任意数量的值进行分组。 tuple 是 TR1 的一部分,许多编译器已将其包含在其标准库实现中。

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

替代文本

std::pair is a data type for grouping two values together as a single object. std::map uses it for key, value pairs.

While you're learning pair, you might check out tuple. It's like pair but for grouping an arbitrary number of values. tuple is part of TR1 and many compilers already include it with their Standard Library implementations.

Also, checkout Chapter 1, "Tuples," of the book The C++ Standard Library Extensions: A Tutorial and Reference by Pete Becker, ISBN-13: 9780321412997, for a thorough explanation.

alt text

篱下浅笙歌 2024-07-12 10:22:43

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

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

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

如果您直接控制类型,那就无关紧要了。

You sometimes need to return 2 values from a function, and it's often overkill to go and create a class just for that.

std:pair comes in handy in those cases.

I think boost:compressed_pair is able to optimize away the members of size 0.
Which is mostly useful for heavy template machinery in libraries.

If you do control the types directly, it's irrelevant.

水晶透心 2024-07-12 10:22:43

听到压缩对关心几个字节听起来很奇怪。 但当人们考虑在哪里可以使用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 个字节。 也就是说,我们非常简单的绑定对象无法放入小缓冲区中,并且需要存储operator new。 如果上面的绑定对象使用 compressed_pa​​ir,它实际上可以将其大小减少到 8 个字节(对于非成员函数指针通常为 4 个字节),因为占位符只不过是一个空对象。

因此,看似仅仅为了几个字节而浪费大量思考实际上可能会对性能产生重大影响。

It can sound strange to hear that compressed_pair cares about a couple of bytes. But it can actually be important when one considers where compressed_pair can be used. For example let's consider this code:

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

It can suddenly have a big impact to use compressed_pair in cases like above. What could happen if boost::bind stores the function pointer and the place-holder _1 as members in itself or in a std::pair in itself? Well, it could bloat up to sizeof(&f) + sizeof(_1). Assuming a function pointer has 8 bytes (not uncommon especially for member functions) and the placeholder has one byte (see Logan's answer for why), then we could have needed 9 bytes for the bind object. Because of aligning, this could bloat up to 12 bytes on a usual 32bit system.

boost::function encourages its implementations to apply a small object optimization. That means that for small functors, a small buffer directly embedded in the boost::function object is used to store the functor. For larger functors, the heap would have to be used by using operator new to get memory. Around boost version 1.34, it was decided to adopt this optimization, because it was figured one could gain some very great performance benefits.

Now, a reasonable (yet, maybe still quite small) limit for such a small buffer would be 8 bytes. That is, our quite simple bind object would not fit into the small buffer, and would require operator new to be stored. If the bind object above would use a compressed_pair, it can actually reduce its size to 8 bytes (or 4 bytes for non-member function pointer often), because the placeholder is nothing more than an empty object.

So, what may look like just wasting a lot of thought for just only a few bytes actually can have a significant impact on performance.

梦幻的味道 2024-07-12 10:22:43

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

boost::compressed_pa​​ir 声称更高效:看这里

It's standard class for storing a pair of values. It's returned/used by some standard functions, like std::map::insert.

boost::compressed_pair claims to be more efficient: see here

讽刺将军 2024-07-12 10:22:43

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

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

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

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

It is just as simple two elements tuple. It was defined in first version of STL in times when compilers were not widely supporting templates and metaprogramming techniques which would be required to implement more sophisticated type of tuple like Boost.Tuple.

It is useful in many situations. std::pair is used in standard associative containers. It can be used as a simple form of range std::pair<iterator, iterator> - so one may define algorithms accepting single object representing range instead of two iterators separately.
(It is a useful alternative in many situations.)

ゝ偶尔ゞ 2024-07-12 10:22:43

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

Sometimes there are two pieces of information that you just always pass around together, whether as a parameter, or a return value, or whatever. Sure, you could write your own object, but if it's just two small primitives or similar, sometimes a pair seems just fine.

甜尕妞 2024-07-12 10:22:43

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

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

Additional info: boost::compressed_pair is useful when one of the pair's types is an empty struct. This is often used in template metaprogramming when the pair's types are programmatically inferred from other types. At then end, you usually have some form of "empty struct".

I would prefer std::pair for any "normal" use, unless you are into heavy template metaprogramming.

〃安静 2024-07-12 10:22:43

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

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

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

It's nothing but a structure with two variables under the hood.

I actually dislike using std::pair for function returns. The reader of the code would have to know what .first is and what .second is.

The compromise I use sometimes is to immediately create constant references to .first and .second, while naming the references clearly.

深海不蓝 2024-07-12 10:22:43

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

例如:

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

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

使用映射和多重映射时,您经常使用指向对的指针来访问元素。

std::pair comes in handy for a couple of the other container classes in the STL.

For example:

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

Both store std::pairs of keys and values.

When using the map and multimap, you often access the elements using a pointer to a pair.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文