c++11知識点の強化

5316 ワード

初期化リスト(std::initializer_list)
  • c++11はstd::initializer_を提供します.listは、クラスオブジェクトの初期化を通常の配列やPODデータと同様に初期化リストを使用することもできるようにします.クラスオブジェクトに初期化リストコンストラクション関数を指定すればよい.
  • std::initializer_listは関数のパラメータとしても使用できます.
  • 初期化リストstd::initializer_List関連サンプルコードは以下の通りです.
  • #include 
    #include 
    #include 
    
    using namespace std;
    
    class InitClass {
    public:
        InitClass(initializer_list list) {
            for (int l : list)
                initializer_list_.emplace_back(l);
        }
    
        void PrintInit() {
            for (int l : initializer_list_)
                cout << l << endl;
        }
    
        void Print(initializer_list list) {
            for (int l : list)
                cout << l << endl;
        }
    
    private:
        vector initializer_list_;
    };
    
    struct A {
        double a;
        int b;
    };
    struct B {
        B(int a, double b): a_(a), b_(b) {}
    private:
        int a_;
        double b_;
    };
    
    
    int main()
    {
        //              
        InitClass i = {1, 2, 3, 4, 5};
        i.PrintInit();
        cout << endl;
        //           
        i.Print({1, 2, 3});
        //           POD  
        vector v = {1, 2, 3, 4};
        A a {1.1, 1};
        B b {2, 2.2};
        
        return 0;
    }

    変長パラメータテンプレート(typename...Args)
  • c++11は、黒魔法に匹敵する変長パラメータテンプレートを提供します.任意のタイプ、任意の数の変長パラメータテンプレートクラス、関数を実現できます.
  • は、典型的な再帰テンプレート関数を用いて、変長パラメータテンプレート関数のパラメータを取り出すことができ、例示的なコードは以下の通りである.
  • #include 
    template
    void printf(T value) {
        std::cout << value << std::endl;
    }
    template
    void printf(T value, Args... args) {
        std::cout << value << std::endl;
        printf(args...);
    }
    int main() {
        printf(1, 2, "123", 1.1);
        return 0;
    }
  • c++14は、初期化リストを使用して変長パラメータを展開できるより簡便な方法を提供し、サンプルコードは以下の通りである.
  • //            -std=c++14
    #include 
    template
    auto print(T value, Args... args) {
        std::cout << value << std::endl;
        return std::initializer_list{([&] {
            std::cout << args << std::endl;
        }(), value)...};
    }
    int main() {
        print(1, 2.1, "123");
        return 0;
    }

    強いタイプ列挙(enum class)
  • c++11は、タイプの安全な列挙クラスenum classを提供する.列挙クラスで定義された列挙値を暗黙的に整数に変換することはできず、整数と直接比較することもできず、異なる列挙タイプの列挙値と比較することもできない.
  • 列挙クラス定義の列挙値は、同じ値を定義することができる.
  • 列挙クラスでは、列挙値のタイプを自分で定義できます.デフォルトはintです.
  • は、リロード<
  • は、テンプレート変換関数を定義して、列挙クラスの列挙値をintなどの基本データ型と直接比較することを容易にすることができる.
  • のすべてのサンプルコードは以下のとおりです.
  • #include 
    enum class new_enum : unsigned int {
        value1,
        value2,
        value3 = 888,
        value4 = 888
    };
    
    template
    std::ostream& operator<::value, std::ostream>::type& stream, const T& e) {
        return stream << static_cast::type>(e);
    }
    
    template
    auto to_underlying_type(const T& e) {
        return static_cast::type>(e);
    }
    
    int main() {
        if (new_enum::value3 == new_enum::value4 && 888 == to_underlying_type(new_enum::value3))
        {
             std::cout << new_enum::value3 << std::endl;
        }
        return 0;
    }

    関数オブジェクトパッケージ(std::function)
  • c++11は、任意の呼び出し可能なタイプを定義できる関数オブジェクトパッケージ(std::function)を提供し、これは関数オブジェクトのタイプに対する安全なパッケージである.
  • std::functionとc++11が提供するより強力なusing構文とLambda関数を利用して、クラスオブジェクトの簡単なコールバック関数をより便利に実現することができます.サンプルコードは次のとおりです.
  • #include 
    #include 
    
    class A {
    public:
        using CallBack = std::function;
    
        void SetCallBack(CallBack cb) { call_back_ = cb; }
        void CallCallBack() {
            if (call_back_)
            {
                call_back_();
            }
            
        }
    
    private:
        CallBack call_back_ = nullptr;
    };
    
    class B {
    public:
        B() {
            a = std::make_shared();
    a->SetCallBack([](){
    std::cout << "call A cb in B" << std::endl;
    });
    a->CallCallBack();
    }
    private:
    std::shared_ptra = nullptr;
    };
    int main() {
    B b;
    }
  • コールバック関数が複雑でLambda関数で実現するのに適していない場合は、std::bindによってクラスのメンバー関数にコールバック関数をバインドすることもできます.

  • スマートポインタ初期化(make_unique)
  • c++のポインタ管理を簡素化するため、c++11は標準ライブラリを拡張し、スマートポインタ-std::shared_を発売した.ptr/std::unique_ptr/std::weak_ptr.インテリジェントポインタは、c++言語をより現代的にするために、参照カウントを使用してリソースを自動的に解放します.
  • 標準ライブラリにはstd::make_が用意されています.sharedはstdを初期化します::shared_ptr、newを使用してstdを初期化することを回避しました::shared_ptr.しかし「標準委員会に忘れられた」ため、標準ライブラリはmakeを提供しなかった.uniqueの方法でstd::unique_を初期化します.ptr(c++14で提供されている).そのために私たちは自分でmakeを実現することができます.Unique、コードは以下の通りです.
  • #include 
    
    template
    std::unique_ptr make_unique( Args&& ...args ) {
        return std::unique_ptr( new T( std::forward(args)... ) );
    }
    
    int main() {
        std::unique_ptr p = make_unique(1);
        return 0;
    }