44

std::pairのために、なぜ私はそれを使用するのですか、そしてどのような利点boost::compressed_pairをもたらしますか?

4

10 に答える 10

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; };

ここで、 とがゼロにならない場合でも同じサイズで問題ありBません。Csizeof(A)

したがってboost::compressed_pair、この最適化を利用して、可能であれば、ペアの型が空の場合はどちらか一方から継承します。

したがって、次のstd::pairようになります(かなりの量、ctorsなどを省略しました):

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

つまり、FirstTypeまたはSecondTypeAである場合、pair<A, int>は より大きくなければなりませんsizeof(int)

しかし、 を使用するcompressed_pairと、生成されたコードは次のようになります。

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

sizeof(int)とcompressed_pair<A,int>同じ大きさになります。

于 2009-02-21T17:51:30.177 に答える
35

std::pair2つの値を1つのオブジェクトとしてグループ化するためのデータ型です。 std::mapキーと値のペアに使用します。

あなたが学んpairでいる間、あなたはチェックアウトするかもしれませんtuple。似pairていますが、任意の数の値をグループ化するためのものです。 tupleはTR1の一部であり、多くのコンパイラはすでに標準ライブラリの実装に含まれています。

また、詳細な説明については、 『 The C ++ Standard Library Extensions:A Tutorial and Reference by Pete Becker、ISBN-13:9780321412997 』の第1章「タプル」を確認してください。

代替テキスト

于 2008-09-18T23:32:20.360 に答える
11

関数から 2 つの値を返す必要がある場合があり、そのためだけにクラスを作成するのはやり過ぎです。

そのような場合に std:pair が役立ちます。

boost:compressed_pa​​ir は、サイズ 0 のメンバーを最適化できると思います。これは、ライブラリ内の重いテンプレート マシンに最も役立ちます。

タイプを直接制御する場合、それは無関係です。

于 2008-09-18T23:21:37.047 に答える
11

compress_pair が数バイトを気にするというのは奇妙に聞こえるかもしれません。しかし、compressed_pa​​ir をどこで使用できるかを考えると、実際には重要になる可能性があります。たとえば、次のコードを考えてみましょう。

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

上記のような場合に、compressed_pa​​ir を使用すると、突然大きな影響を与える可能性があります。boost::bind が関数ポインターとプレースホルダー_1をメンバーとしてそれ自体または a 自体に格納するとどうなるstd::pairでしょうか? まあ、それは まで膨張する可能性がありsizeof(&f) + sizeof(_1)ます。関数ポインターが 8 バイト (特にメンバー関数では珍しくありません) で、プレースホルダーが 1 バイト (理由については Logan の回答を参照) であると仮定すると、バインド オブジェクトに 9 バイトが必要になる可能性があります。アラインメントのため、これは通常の 32 ビット システムで最大 12 バイトまで肥大化する可能性があります。

boost::function実装が小さなオブジェクトの最適化を適用することをお勧めします。つまり、小さなboost::functionファンクターの場合、オブジェクトに直接埋め込まれた小さなバッファーを使用してファンクターを格納します。より大きなファンクターの場合、メモリを取得するために operator new を使用してヒープを使用する必要があります。ブーストバージョン 1.34前後で、この最適化を採用することが決定されました。非常に優れたパフォーマンス上の利点が得られると考えられたためです。

現在、このような小さなバッファーの妥当な (まだかなり小さい) 制限は 8 バイトです。つまり、非常に単純なバインド オブジェクトは小さなバッファーに収まらず、新しい演算子を格納する必要があります上記のバインド オブジェクトが を使用する場合compressed_pair、プレースホルダーは空のオブジェクトにすぎないため、実際にはサイズを 8 バイト (非メンバー関数ポインターの場合は 4 バイト) に減らすことができます。

したがって、ほんの数バイトのために多くの考えを無駄にしているように見えるかもしれませんが、実際にはパフォーマンスに大きな影響を与える可能性があります。

于 2009-02-21T19:11:24.540 に答える
3

std::pair とは何ですか? なぜ使用するのでしょうか?

それは単純な 2 つの要素のタプルです。Boost.Tupleのようなより洗練されたタイプのタプルを実装するために必要なテンプレートやメタプログラミング手法をコンパイラが広くサポートしていなかった時代に、 STLの最初のバージョンで定義されました。

多くの状況で役立ちます。std::pair標準の連想コンテナで使用されます。これは範囲の単純な形式として使用できますstd::pair<iterator, iterator>。そのため、2 つの反復子を別々に使用する代わりに、範囲を表す単一のオブジェクトを受け入れるアルゴリズムを定義できます。(これは、多くの状況で便利な代替手段です。)

于 2010-01-23T19:25:56.730 に答える
3

std::pair は、STL の他のいくつかのコンテナー クラスに役立ちます。

例えば:

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

どちらもキーと値の std::pair を格納します。

マップとマルチマップを使用する場合、ペアへのポインターを使用して要素にアクセスすることがよくあります。

于 2008-09-18T23:24:40.737 に答える
3

値のペアを格納するための標準クラスです。のようないくつかの標準関数によって返されます/使用されstd::map::insertます。

boost::compressed_pairより効率的であると主張しています:ここを参照してください

于 2008-09-18T23:25:09.830 に答える
3

追加情報: boost::compressed_pa​​ir は、ペアの型の 1 つが空の構造体である場合に役立ちます。これは、ペアの型が他の型からプログラムによって推論される場合に、テンプレートのメタプログラミングでよく使用されます。最後に、通常、何らかの形の「空の構造体」があります。

重いテンプレートメタプログラミングに興味がない限り、「通常の」使用には std::pair をお勧めします。

于 2008-09-23T11:48:18.317 に答える
3

これは、内部に 2 つの変数がある構造に他なりません。

関数の戻り値に std::pair を使用するのは実際には嫌いです。コードの読者は、.first とは何か、.second とは何かを知っている必要があります。

私が時々使用する妥協案は、参照に明確な名前を付けながら、.first と .second への定数参照をすぐに作成することです。

于 2009-02-21T17:31:57.180 に答える
1

パラメータや戻り値など、常に一緒に渡す 2 つの情報がある場合があります。もちろん、独自のオブジェクトを作成することもできますが、それが 2 つの小さなプリミティブなどである場合は、ペアで問題ないように見えることがあります。

于 2008-09-18T23:26:45.677 に答える