ぷるぷるの雑記

低レイヤーがんばるぞいなブログ. 記事のご利用は自己責任で.

C++のpair型の使い方

実行環境は mingw (GCC 11.2.0)

初期化

ヘルパ関数std::make_pair()か、初期化子を使うと初期化できる.

#include<iostream>
using namespace std;

int main()
{
    pair<int,int> p1=make_pair(1,2);
    pair<int,int> p2={1,2};
    
    // 定義後にも使用可能
    p1 = make_pair(3,4);
    p2 = {3,4};
    
}


ただし、std::make_pair()はpairクラスのオブジェクトを生成するのに対し、初期化子はあくまで初期化子である. したがってmake_pair(1,2).firstのような記述はできるが、{1,2}.firstのような記述はできない(初期化子はpair型専用ではないので、firstr、secondというメンバがあるとは限らない).

#include<iostream>
#include<stdio.h>
using namespace std;

int main()
{
    cout << make_pair(1,2).first << endl;
    /* Compile Error
    cout << {1,2}.first << endl;
    */

}

要素へのアクセス

p.first、p.secondのようにアクセスする.

標準出力への表示

pair型はストリーム出力に対応していないので、個別に要素を出力する必要がある.

#include<iostream>
using namespace std;

int main()
{
    pair<int,int> p={1,2};
    cout << "p.first:" <<p.first << " p.second:" << p.second << endl;
    /* Compile Error
    cout << p << endl;
    */
}

代入

pair型は代入演算子が定義されている. 特別な操作が不要な場合、firstとsecondを個別に代入する必要はない.

#include<iostream>
#include<stdio.h>
using namespace std;

int main()
{
    pair<int,int> p1={1,2};
    pair<int,int> p2={3,4};
    cout << p1.first << p1.second << endl; // 12
    p1 = p2;
    cout << p1.first << p1.second << endl; // 34
}


シャローコピーとなるかどうかはpair型が格納している型の代入演算子の実装に依存する. 以下のような自作クラスの場合、いわゆるシャローコピーのようになる.

#include<iostream>
using namespace std;

class MyClass{
public:
    int* pNum;

    MyClass(int* num):pNum(num){}

    MyClass operator =(MyClass obj){
        // (実用的かはさておいて)ポインタを共有する
        this->pNum = obj.pNum;
        return *(this);
    }

    void setVal(int val){
        *(pNum)=val;
    }

    int getVal(){
        return *(pNum);
    }
};

int main()
{
    int num=5;
    pair<int, MyClass> p1 = {1, MyClass(&num)};
    cout << p1.second.getVal() << endl;          // 5
    
    // MyClassの代入演算子の場合p2の変更がp1にも影響を及ぼす
    pair<int, MyClass> p2 = p1;
    p2.second.setVal(10);

    cout << p1.second.getVal() << endl;     // not 5, but 10
}

比較演算子

以下左辺をx、右辺をyとする. 実際は==、!=、<、<=、>、>= が定義されている.

==

x.firstの値とy.firstの値が等しく、かつx.secondの値とy.secondが等しいときtrue、そうでなければfalseを返す. すなわち、次式を返す

return x.first == y.first && x.second == y.second;

<

y.firstの値がx.firstの値より大きければtrueを返す. y.first==x.firstだった場合は、f.secondの値がx.secondの値より大きければtrueを返す. いずれでもない場合はfalseを返す. すなわち、次式を返す.

return x.first < y.first || (!(y.first < x.first) && x.second < y.second);

構造化束縛

型推論と構造化束縛を使うと、pair型のfirstとsecondの要素をかっこよく取り出すことが出来る.

#include<iostream>
#include<stdio.h>
using namespace std;

int main()
{
    pair<int,char> p={1,'p'};

    // 型推論 + 構造化束縛 (C++17以降)
    auto [n,c] = p;
    cout << "n:" << n << " c:" << c << endl;  // n:1 c:p
}

参考

cpprefjp.github.io

detail.chiebukuro.yahoo.co.jp