215

の目的はstd::make_pair何ですか?

なぜそうしないのstd::pair<int, char>(0, 'a')ですか?

2つの方法に違いはありますか?

4

7 に答える 7

199

違いは、 withstd::pairは両方の要素の型を指定する必要があるのに対し、std::make_pairは渡された要素の型とペアを作成し、それを伝える必要がないことです。とにかく、それは私がさまざまなドキュメントから収集できたものです。

http://www.cplusplus.com/reference/std/utility/make_pair/からこの例を参照してください

pair <int,int> one;
pair <int,int> two;

one = make_pair (10,20);
two = make_pair (10.5,'A'); // ok: implicit conversion from pair<double,char>

それの暗黙の変換ボーナスは別として、make_pair を使用しなかった場合は、次のことを行う必要があります。

one = pair<int,int>(10,20)

あなたが1つに割り当てるたびに、それは時間の経過とともに迷惑になります...

于 2012-02-14T01:39:57.687 に答える
45

@MSalters が上で回答したように、中かっこを使用して C++11 でこれを行うことができるようになりました (C++11 コンパイラでこれを確認しました)。

pair<int, int> p = {1, 2};
于 2014-02-24T18:28:47.870 に答える
43

クラス テンプレート引数は、C++17 より前のコンストラクターから推論できませんでした

C++17 より前では、次のようなものを書くことはできませんでした。

std::pair p(1, 'a');

コンストラクターの引数からテンプレートの型を推測するため、次のように明示的に記述する必要がありました。

std::pair<int,char> p(1, 'a');

C++17 ではその構文が可能になるため、make_pair冗長になります。

C++17 より前では、std::make_pairあまり冗長でないコードを書くことができました。

MyLongClassName1 o1;
MyLongClassName2 o2;
auto p = std::make_pair(o1, o2);

より冗長な代わりに:

std::pair<MyLongClassName1,MyLongClassName2> p{o1, o2};

タイプを繰り返すため、非常に長くなる可能性があります。

make_pairはコンストラクターではないため、型推論は C++17 より前のケースで機能します。

make_pair基本的に次と同等です。

template<class T1, class T2>
std::pair<T1, T2> my_make_pair(T1 t1, T2 t2) {
    return std::pair<T1, T2>(t1, t2);
}

insertervsにも同じ概念が適用されinsert_iteratorます。

以下も参照してください。

最小限の例

物事をより具体的にするために、次の方法で問題を最小限に観察できます。

main.cpp

template <class MyType>
struct MyClass {
    MyType i;
    MyClass(MyType i) : i(i) {}
};

template<class MyType>
MyClass<MyType> make_my_class(MyType i) {
    return MyClass<MyType>(i);
}

int main() {
    MyClass<int> my_class(1);
}

それから:

g++-8 -Wall -Wextra -Wpedantic -std=c++17 main.cpp

うまくコンパイルされますが、次のようになります。

g++-8 -Wall -Wextra -Wpedantic -std=c++14 main.cpp

次のエラーで失敗します:

main.cpp: In function ‘int main()’:
main.cpp:13:13: error: missing template arguments before ‘my_class’
     MyClass my_class(1);
             ^~~~~~~~

代わりに動作する必要があります:

MyClass<int> my_class(1);

またはヘルパー:

auto my_class = make_my_class(1);

コンストラクターの代わりに通常の関数を使用します。

の違いstd::reference_wrapper

This commentstd::make_pairは、コンストラクターがアンラップしないのにアンラップすることに言及しているstd::reference_wrapperため、それが1つの違いです。TODO の例。

GCC 8.1.0、Ubuntu 16.04 でテスト済み。

于 2017-01-07T12:26:41.200 に答える
26

指定された型引数でコンストラクターを使用することmake_pairと明示的に呼び出すことに違いはありません。テンプレートメソッドには指定されたパラメーターに基づく型推定があるため、型が冗長な場合はより便利です。例えば、pairstd::make_pair

std::vector< std::pair< std::vector<int>, std::vector<int> > > vecOfPair;
std::vector<int> emptyV;

// shorter
vecOfPair.push_back(std::make_pair(emptyV, emptyV));

 // longer
vecOfPair.push_back(std::pair< std::vector<int>, std::vector<int> >(emptyV, emptyV));
于 2012-02-14T01:49:24.283 に答える
21

これは、C++ テンプレート プログラミングの一般的なイディオムであることに注意してください。これはオブジェクト ジェネレーターのイディオムとして知られています。詳細と適切な例については、こちらを参照してください。

編集コメントで誰かが提案したように(削除されたため)、以下は、リンクが壊れた場合に備えて、リンクからわずかに変更された抜粋です。

オブジェクト ジェネレーターを使用すると、オブジェクトの型を明示的に指定せずにオブジェクトを作成できます。これは、クラス テンプレートにはない関数テンプレートの便利なプロパティに基づいています。関数テンプレートの型パラメーターは、実際のパラメーターから自動的に推定されます。関数の実際のパラメーターに応じてテンプレートstd::make_pairのインスタンスを返す簡単な例です。std::pairstd::make_pair

template <class T, class U>
std::pair <T, U> 
make_pair(T t, U u)
{
  return std::pair <T, U> (t,u);
}
于 2013-03-15T14:35:40.623 に答える
5

make_pair は、直接コンストラクターに余分なコピーを作成します。単純な構文を提供するために、常にペアを型定義します。
これは違いを示しています (Rampal Chaudhary による例):

class Sample
{
    static int _noOfObjects;

    int _objectNo;
public:
    Sample() :
        _objectNo( _noOfObjects++ )
    {
        std::cout<<"Inside default constructor of object "<<_objectNo<<std::endl;
    }

    Sample( const Sample& sample) :
    _objectNo( _noOfObjects++ )
    {
        std::cout<<"Inside copy constructor of object "<<_objectNo<<std::endl;
    }

    ~Sample()
    {
        std::cout<<"Destroying object "<<_objectNo<<std::endl;
    }
};
int Sample::_noOfObjects = 0;


int main(int argc, char* argv[])
{
    Sample sample;
    std::map<int,Sample> map;

    map.insert( std::make_pair( 1, sample) );
    //map.insert( std::pair<int,Sample>( 1, sample) );
    return 0;
}
于 2013-11-28T13:40:41.543 に答える