連想コンテナ(第3章)(第19条、第20条)

第19条:平等と同等の違いを理解する

連想コンテナセット/マルチセット、マップ/マルチマップには、コンテナ要素の順序付けルールを決定するために使用されるテンプレートパラメータがあります。標準タイプlessが使用され、セット、マップなどの要素のみが使用されます。同等性を定義します。

テンプレートクラスマップの形式は次のとおりです。

std::map
template < class Key,                                     // map::key_type
           class T,                                       // map::mapped_type
           class Compare = less<Key>,                     // map::key_compare
           class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
           > class map;

標準のテンプレートクラスセットの形式は次のとおりです。

std::set
template < class T,                        // set::key_type/value_type
           class Compare = less<T>,        // set::key_compare/value_compare
           class Alloc = allocator<T>      // set::allocator_type
           > class set;

同等性は次のように定義されます。素人の用語では、aはbの前になく、bはaの前にありませんが、同等性と同じではありません。等しい場合、2つのコンテナの要素は同等である可能性がありますが、等しくなければならない

!comp(a,b) && !comp(b,a))

例、文字列間の大文字と小文字を区別しない比較の実装(少し低い場合があります、文字列はコピーされます、これは無視するポイントではありません)

    // string不区分大小写的比较
    struct CIStringCompare : public std::binary_function<string, string, bool> {
        bool operator()(const string &lhs, const string &rhs) const {
            string lstr(lhs);
            std::transform(lhs.cbegin(), lhs.cend(), lstr.begin(), tolower);
            string rstr(rhs);
            std::transform(rhs.cbegin(), rhs.cend(), rstr.begin(), tolower);
            return lstr < rstr;
        }
    };


    void test_19() {
        set<string, CIStringCompare> ciss; // 不区分大小写的字符串集合
        ciss.insert("Persephone"); // 显然,这两个字符串不相等,但是根据我们对排序规则的定义,它们是等价的
        ciss.insert("persephone");
        std::for_each(ciss.cbegin(), ciss.cend(), [](const string &str) { std::cout << str << std::endl; });

        return;
    }

項目20:ポインターを含む連想コンテナーの比較タイプを指定します

文字列*を含むセットコンテナを定義し、いくつかの動物の名前を1つずつセットに挿入してから、以下に示すように1つずつ印刷するとします。そうです、あなたは孤独を印刷しました。文字列*である要素。文字列を出力するには、ポインタの内容を取得するために*を追加する必要があります。

    void test_20() {
        set<string *> ssp;
        ssp.insert(new string("anteater"));
        ssp.insert(new string("wombat"));
        ssp.insert(new string("lemur"));
        ssp.insert(new string("penguin"));
        for(auto iter = ssp.cbegin(); iter != ssp.cend(); ++iter) {
            std::cout << *iter << std::endl;
        }

        return;
    }

输出:
0x3a5170
0x3a5220
0x3a52d0
0x3a5380

変更後は正常です

std::cout << **iter << std::endl;

输出:
anteater
wombat
lemur
penguin

上記のどれも重要ではありません。コンテナ要素はポインタであり、デフォルトではポインタの並べ替えが少ないため、文字列がルールに従って並べ替えられない理由に気づきましたか。文字列の問題なので、この句のコアは次のようになります。ポインタ用に書かれていますか?以下に示すように、あなた自身の比較タイプを見つけてください。

    // string*比较
    struct StrPtrCompare : public std::binary_function<string *, string *, bool> {
        bool operator()(const string *lhs, const string *rhs) const {
            return *lhs < *rhs;
        }
    };

    void test_20() {
        set<string *, StrPtrCompare> ssp;
        ssp.insert(new string("anteater"));
        ssp.insert(new string("wombat"));
        ssp.insert(new string("lemur"));
        ssp.insert(new string("penguin"));
        for (auto iter = ssp.cbegin(); iter != ssp.cend(); ++iter) {
            std::cout << **iter << std::endl;
        }

        return;
    }

输出:
anteater
lemur
penguin
wombat

ちょっと待ってください、まだ終わっていません。実際に新しい文字列を配列に直接挿入します。メモリを自分で管理してから、1つずつ削除して解放しますか?いいえ、C ++ 11はスマートポインタを提供します

    // std::shared_ptr<string>比较
    struct SharedPtrCompare : public std::binary_function<std::shared_ptr<string>, std::shared_ptr<string>, bool> {
        bool operator()(const std::shared_ptr<string> &lhs, const std::shared_ptr<string> &rhs) const {
            return *lhs < *rhs;
        }
    };

    void test_20() {
        // 智能指针
        set<std::shared_ptr<string>, SharedPtrCompare> sSharedp;
        sSharedp.insert(std::make_shared<string>("anteater"));
        sSharedp.insert(std::make_shared<string>("wombat"));
        sSharedp.insert(std::make_shared<string>("lemur"));
        sSharedp.insert(std::make_shared<string>("penguin"));
        for (auto iter = sSharedp.cbegin(); iter != sSharedp.cend(); ++iter) {
            std::cout << **iter << std::endl;
        }
        
        return;
    }

输出:
anteater
lemur
penguin
wombat

最後に、テンプレートを定義するのは良くありませんか?なぜ各タイプの比較タイプを定義するのですか?

    // 为指针、智能指针定义的通用比较模板类
    struct DereferenceLess {
        template<typename PtrType>
        bool operator()(PtrType p1, PtrType p2) const {
            return *p1 < *p2;
        }
    };

    void test_20() {
        // 普通指针
//        set<string *, StrPtrCompare> ssp;
        set<string *, DereferenceLess> ssp;
        ssp.insert(new string("anteater"));
        ssp.insert(new string("wombat"));
        ssp.insert(new string("lemur"));
        ssp.insert(new string("penguin"));
        for (auto iter = ssp.cbegin(); iter != ssp.cend(); ++iter) {
            std::cout << **iter << std::endl;
        }

        // 智能指针
//        set<std::shared_ptr<string>, SharedPtrCompare> sSharedp;
        set<std::shared_ptr<string>, DereferenceLess> sSharedp;
        sSharedp.insert(std::make_shared<string>("anteater"));
        sSharedp.insert(std::make_shared<string>("wombat"));
        sSharedp.insert(std::make_shared<string>("lemur"));
        sSharedp.insert(std::make_shared<string>("penguin"));
        for (auto iter = sSharedp.cbegin(); iter != sSharedp.cend(); ++iter) {
            std::cout << **iter << std::endl;
        }

        return;
    }

输出:
anteater
lemur
penguin
wombat
anteater
lemur
penguin
wombat

参照:「EffectiveSTLChineseEdition」の第3章

おすすめ

転載: blog.csdn.net/u010323563/article/details/112382157