ゼロから始まる単純関数式C+(一)pair

20469 ワード

STLの主なツールSTLには、多くのコンテナが用意されているだけでなく、2つの基本的なデータ単位が用意されています.データ単位と呼ぶのは、本質的にpairとtupleが2つの共通のデータ型テンプレートであるからです.もっと簡単に言えば、肝心なのは2つの点で、その1つは通用して、つまり随用随写することができて、その2つはテンプレートで、つまり彼の具体的な実現方法です.
2つのデータをパッケージするメタグループpairは、データのバインドという簡単な問題に直面します.例えば、あなたは学習グループを持っていて、一人一人の名前と彼の学習能力の2つのデータがこのグループのすべてのメンバーのエンティティを構成しています.名前はstringタイプ、学習能力はintタイプと仮定し、最も伝統的な方法はデータのみの構造体を構築することである.今pairがあれば、前の冗長な構造体宣言の代わりにpairを直接使うだけで、使用も簡単です.具体的には以下のコードを参照してください.
#include 
#include 
#include 
#include 

int main()
{
    std::string names[3] = { "alice", "bob", "carl" };
    int score[3] = { 5, 6, 7 };

    // build a pair from string and int
    std::pair<std::string, int> p0 = std::make_pair(names[0], score[0]);
    std::cout << "The value of p0 is "
              << "(" << p0.first << ", " << p0.second << ")
"
; // => The value of p0 is (alice, 5) // build a pair from string and std::ref(int) auto p1 = std::make_pair(names[1], std::ref(score[1])); std::cout << "The value of p1 is " << "(" << p1.first << ", " << p1.second << ")
"
; // => The value of p1 is (bob, 6) score[1] += 10; std::cout << "After score[1] += 10, the value of p1 is " << "(" << p1.first << ", " << p1.second << ")
"
; // => After score[1] += 10, the value of p1 is (bob, 16) p1.second += 100; std::cout << "After p1.second += 100, the value of p1 is " << "(" << p1.first << ", " << p1.second << "), " << "while score[1] is " << score[1] << "
"
; // => After p1.second += 100, the value of p1 is (bob, 116), while score[1] is 116 names[1] += "bi"; std::cout << "After names[1] += \"bi\", the value of p1 is " << "(" << p1.first << ", " << p1.second << "), " << "while names[1] is " << names[1] << "
"
; // => After names[1] += "bi", the value of p1 is (bob, 116), while names[1] is bobbi return 0; } // filename: ch1-pair-example-1.cpp // compile this> g++ ch1-pair-example-1.cpp -o ch1-pair-example-1.exe

このコードには、以下の点を追加する必要があります.
3~4行目に必要なヘッダファイルが追加されました.std::pair<>およびstd::make_pair()はヘッダファイルの中にあり、std::ref()はヘッダファイルの中にあります.8行目から9行目までのデータは予め定義、12行目には1つのメタグループp 0が明示的に定義され、13行目から14行目にはそれぞれp 0が使用される.firstとp 0.secondはそのデータを選択して出力する.18行目の前半はコンパイル時のタイプ導出機能を用いて同様にメタグループp 1を定義し、キーワードautoは使用タイプ導出を表す.18行目の後半はstd::ref()でscore[1]の参照タイプが製造するており、22行目で修正するとメタグループp 1の値も変化し、26行目で直接p 1になることに注目できる.secondが変更された後、元のデータscore[1]も変更された.31行目ではnames[1]の値を変更したが、p 1の内部取値には影響しなかった.上記のコードからpairの簡単な特性を推測するのは難しくない.
pairは2つの要素のみを含む1つのテンプレートクラスであり、使用時に明示的な宣言または暗黙的な導出によってテンプレートを特化する必要があり、それによって私たちが必要とする特定のタイプを製造し、言い換えれば、いかなるタイプの導出エラーもコンパイル時のエラーを引き起こす.pairはfirstとsecondの2つのデータメンバーのみを含み、そのタイプとデータ値は宣言時のコード書き順に順次対応している.autoは、ポインタや参照ではなく、タイプ導出時にデフォルトでベースタイプを使用します.std::ref()などの明示的な参照が初期化時に使用された場合にのみ、タイプを参照タイプに変更します.以上のことを考えた上で、pairの定義声明を読むのは難しくありません.
namespace std{
    template<class T1, class T2>
    struct pair
    {
        using first_type = T1;
        using second_type = T2;
        T1 first;
        T2 second;
        pair(const pair&) = default;
        pair(pair&&) = default;
        constexpr pair();
        constexpr pair(const T1& x, const T2& y);
        template<class U, class V> constexpr pair(U&& x, V&& y);
        template<class U, class V> constexpr pair(const pair<U, V>& p);
        template<class U, class V> constexpr pair(pair<U, V>&& p);
        pair& operator=(const pair& p);
        template<class U, class V> pair& operator=(const pair<U, V>& p);
        pair& operator=(pair&& p) noexcept();
        template<class U, class V> pair& operator=(pair<U, V>&& p);
        void swap(pair& p) noexcept();
    };
}
// filename: ch1-pair-defination-simplified.cpp



この定義を借りてpair内蔵の他の方法をさらに理解します.
#include #include #include #include
using namespace std;
template ostream& operator< &_) { return out << “(” << _.first << ", "<< _.second << “)”; }
void display_separator() { cout << “--------” << endl; }
int main() { pair p1;//=> (0, 0) cout << "Default constructor: "<< p1 << endl; pair p2(65, 1.1);//=> (65, 1.1) cout << "Initialized with two values: "<< p2 << endl; pair p3(p2);//=> (65, 1.1) cout << "Copy constructor: "<< p3 << endl; pair p4(p2);//=> (A, 1) cout << "Copy then convert: "<< p4 << endl;
display_separator();

pair p5 = make_pair('B', 2);
cout << "Before swap: p4 is " << p4 << " , p5 is " << p5 << endl;
// => Before swap: p4 is (A, 1) , p5 is (B, 2)
p5.swap(p4);
cout << "After swap: p4 is " << p4 << " , p5 is " << p5 << endl;
// => After swap: p4 is (B, 2) , p5 is (A, 1)

display_separator();

pair p6 = make_pair('B', 1);
pair p7 = make_pair('A', 2);
cout << "p4 is " << p4 << " , p5 is " << p5 << ", "
     << "p6 is " << p6 << " , p7 is " << p7 << endl;
// => p4 is (B, 2) , p5 is (A, 1), p6 is (B, 1) , p7 is (A, 2)
cout << std::boolalpha;
cout << (p4 == p5) << endl; // => false
cout << (p4 != p5) << endl; // => true
cout << (p5 < p7) << endl; // => true
cout << (p4 < p6) << endl; // => false
cout << (p5 < p6) << endl; // => true
cout << (p6 < p7) << endl; // => false
return 0;

}
この例では、以下の点を明記する必要があります.
18-25行目はpairの初期化方法を簡単に紹介していますが、もちろんもっと簡単なstd::make_pair()は値を付与することによって初期化される.32行目では、組み込まれたswap()メソッドを使用しています.このメソッドは、2つのpairのタイプが完全に一致している場合にのみ使用できます.そうしないと、コンパイルエラーが報告されます.44行目から49行目に内蔵された比較演算子operator==()とoperatorをテストし、pairは二メタデータグループを操作するより簡便な方法を提供し、同時にいくつかの一般的な組み込み方法を持っているため、自己組織構造体に比べて天然の優位性を持っている.またpairは、標準ライブラリ内のすべてのキー値データ(key-value data)のデフォルトの戻りタイプでもあり、pairは標準ライブラリを迅速に使用する最初のキーであり、それを熟練して使用することが標準ライブラリを熟練する最初のステップであることを誇張しない.
polossk/Zero-Kara-FCPP