c++11ノート

41649 ワード

文書ディレクトリ
  • 1.std::thread
  • 2.std::bind
  • 3.std::ref
  • 4.std::move
  • 5.std::vector
  • 6.std::function
  • 7.Lambda式
  • 8.原子操作
  • 9.Container::emplace
  • 10、右参照、noexcept、=delete呼び出し可能オブジェクト
  • 11.インテリジェントポインタ
  • 1.std::thread
  • /usr/include/c++/4.8/threadの中に完全なthread類声明
  • があるのを見ることができます.
  • std::thread新しいスレッドを作成すると、lambda式(変数付きキャプチャまたはなし)、関数、関数オブジェクト、および関数ポインタを含む任意の呼び出し可能なオブジェクトタイプ(パラメータ付きまたはパラメータなし)を受け入れることができます.
  • 入力関数ポインタとパラメータスレッドは直ちに実行する.空の構造ではスレッド
  • は追加されません.
    std::thread t(fun); //fun     
    t.join();
    
  • は、std::this_thread::get_id()によって取得するスレッドの識別子を直接t.get_id()
  • とすることもできる.
  • std::thread::idは比較可能で、関連コンテナのkey(std::thread::idはoperator==を再ロードし、2つのスレッドが等しいかどうかを比較できる)
  • 注意std::threadの等しいオペレータはmoveの意味を通過しなければなりません.joinableの場合、std::terminate()が実行されます.
    https://www.ibm.com/developerworks/cn/linux/1412_zhupx_thread/
    2.std::bind
    関数とパラメータをバインドし、関数オブジェクトを返します.
    auto fn_1 = std::bind(my_divide,10,2); //  10/2
    std::cout<<fn_1()<<endl;
    auto fn_2 = std::bind<int>(my_divide,_1,_2) //  int(x/y)
    std::cout<<fn_2(10,3)<<endl;
    

    std::bindは呼び出し可能なオブジェクトをパラメータとともにバインドし、バインド後の結果はstd::functionで保存できます.
    呼び出し可能なオブジェクトとそのパラメータを関数にバインド
    一部のパラメータのみをバインドし、呼び出し可能なオブジェクトからのパラメータを減らす
    std::bindとstd::functionはバインドメンバー関数を使用します.バインドメンバー変数は6を参照してください.std::function
    3.std::ref
    std::bindは、参照ではなくパラメータを直接コピーし、パラメータを直接操作しません.
    彼をコピーせずにbindにオブジェクトを渡すには、標準ライブラリref関数を使用する必要があります.
    for_each(words.begin(), words.end(), std::bind(print, std::ref(os), _1, ' '))
    

    (//このusingは_1,_2,_3,...プレースホルダusingnamespace std::placeholders;を使用するためです)
    関数refは、コピー可能な所定の参照を含むオブジェクトを返す.
    ⤵️std::crefはconst参照を保存するクラスを生成します.#include
    4.std::move
    右の値がARGに参照され、意味値を強制的に移動する補助関数を返します.static_cast::type&&>(arg)
    左参照を右参照に変換できます
    不要なコピーを排除し、パフォーマンスを向上
    オブジェクトのステータスまたは所有権を1つのオブジェクトから別のオブジェクトに移動します.ただし、移行、メモリの移行、またはメモリコピーはありません.
        std::string a = "hello";
        std::string b = "world";
        std::cout<<"a "<<a<<std::endl;
        std::cout<<"b "<<b<<std::endl;
    
        a = std::move(b);
        std::cout<<"a "<<a<<std::endl;
        std::cout<<"b "<<b<<std::endl;  
    

    しゅつりょく
    a hello
    b world
    a world
    b 
    

    直接bのすべてをaにあげて、bの中にはもう何もなくて、直接bを住所の所有権に指してaにあげて、bはもうその住所を指しません
    5.std::vector
    vectorの遍歴にはいい栗があります
    std::vector<std::string> myvector;
    std::string foo = "foo-string";
    myvector.push_back(foo);
    for(std::string& x:myvector) std::cout<<' '<<x;  //        
    std::cout<<'
    '
    ;

    追加
    obj.push_back(foo);
    

    消去
     obj.erase(obj.begin() + 4);
    

    obj.front()とobj.begin()の違い
    frontは戻り参照、beginは反復器を返します
    同じ理屈でbackとend
    一般的なソート時に反復器で示す
    sort(obj.begin(), obj.end());
    reverse(obj.begin(), obj.end());//  
    sort(obj.rbegin(), obj.rend());//    
    
  • capacity()は、現在割り当てられている記憶容量
  • を返す.
    6.std::function
    呼び出し可能なオブジェクトのパッケージであり、最も重要な機能は遅延呼び出しを実現することです.
    関数ポインタとして理解できます
  • フリー関数
  • を保存
    void printA(int a)
    {
        cout<<a<<endl;
    }
    std::function<void(int a)> func;
    func = printA;
    func(2);
    
  • 保存lambda式は本質的に匿名関数オブジェクト
  • である.
    std::functionfunc_1 = [](){cout<
  • std::bindは呼び出し可能なオブジェクトをそのパラメータにバインドします.バインド後std::functionを使用して保存し、遅刻を遅らせることができます.必要なときに使用します.
  • 呼び出し可能なオブジェクトとそのパラメータを擬似関数
  • にバインドする.
  • バインド可能部分パラメータ
  • 部分パラメータをバインドする場合、std::placeholdersを使用することによって、空格子点パラメータが呼び出し発生時のいくつかのパラメータ
    #include 
    class A {
    public:
        int i_ = 0; //c11                   
        void output(int x, int y)
        {
            std::cout<<x<<" "<<y<<std::endl;
        }
    private:
        int j_;
    };
    int main()
    {
        A a;
        //      ,      
        std::function<void(int, int)>fun1 = std::bind(&A::output, &a, std::placeholders::_1, std::placeholders::_2);
        //      
        fun1(1,2);
    
        //      
        std::function<int&(void)>fun2 = std::bind(&A::i_, &a);
        //std::functionfun2 = std::bind(&A::j_, &a); //          
        fun2() = 100;
        fun2() = 100;
        std::cout<<a.j_<<std::endl;
    
    }   
    
    となることを決定する.
    7.lambda式
    本質的には匿名関数オブジェクト
    メリット:
  • は同じ関数オブジェクトですが、
  • がすぐに表示されます.
  • 匿名の対象で、ブロックを使い終わったらすぐに解放され、ネーミングスペース
  • を汚染しません.
  • std::bind,lambda exprより効率的に向上
  • 心智負担を減らす(コールバック機構によりコード分岐がゼロになる)
  • 8.原子操作
    ヘッダファイル#include 基本実現std::atomic拡張実現std::atomic_char,std::atomiic_int,std::atomic_uintマルチスレッド共有リソースが乱順にアクセスされないようにするために,単一ステップ操作を短くして「分割できないほど小さい」原子操作を実現するためである.
    内蔵のデータ構造を使用するように、原子データ型(c++は、これらの操作が原子操作であることを保証します)を使用して内蔵のデータ型に対応することができます.原子データには対応するタイプがあります.詳細は、次の項を参照してください.http://en.cppreference.com/w/cpp/atomic/atomic std::atomic_long sum = {0L};
    std::atomic_long sum = {0L};  //long sum = 0L;
    //                  sum               
    void fun()
    {
        for(int i=0;i<100000;++i)
            sum += i;
    }
     
    int main()
    {
        std::cout << "Before joining,sun = " << sum << std::endl;
        std::thread t1(fun);
        std::thread t2(fun);
        t1.join();
        t2.join();
        std::cout << "After joining,sun = " << sum << std::endl;
    }
    
    
         
    Before joining,sun = 0
    After joining,sun = 9999900000
     
    Before joining,sun = 0
    After joining,sun = 7928483429
    

    9.Container::emplace
    コピーの削減、効率化
    10、右参照、noexcept、=delete呼び出し可能オブジェクト
    =delete thread(const thread&) = delete;コピー構造の無効化
  • noexceptこのキーワードはコンパイラに、関数に異常が発生しないことを伝え、コンパイラがプログラムをより最適化するのに役立つ.実行時にnoexecpt関数が外に異常を投げ出すと、プログラムは直接終了し、std::terminate()関数を呼び出し、この関数の内部でstd::abort()を呼び出してプログラムを終了する.throw()
      constexpr initializer_list() noexcept
          : _M_array(0), _M_len(0) { }
    
    void swap(Type& x, Type& y) throw()   //C++11  
    {
         x.swap(y);
    }
    void swap(Type& x, Type& y) noexcept  //C++11
    {
          x.swap(y);
    }//    noexcept,       swap         
    
    
    の使用方法にある程度取って代わった彼は、モバイル割り当て関数(move assignment)の応用
  • においても、より柔軟に
    void swap(Type&x, Type& y) noexcept(noexcept(x.swap(y))) //c++11
    {
        x.swap(y);
    }//       x.swap(y)     ,    swap(Type& x, Type& y)       
    
    を使用することができる.
       pair& operator=(pair&& __p)
         noexcept(__and_<is_nothrow_move_assignable<_T1>,
                         is_nothrow_move_assignable<_T2>>::value)
         {
             first = std::forward<first_type>(__p.first);
             second = std::forward<second_type>(__p.second);
             return *this;
         }
     //       T1 T2             ,                
    

    いつ使うことを提案します(その他の時使うことを提案しません!):
  • モバイルコンストラクタ
  • 移動割当関数(move assignment)
  • 構造関数(destructor)
  • リーフ関数(Leaf Function).リーフ関数とは、関数内部にスタック空間を割り当てず、他の関数も呼び出さず、不揮発性レジスタも格納せず、異常も処理しないことを意味する.
  • .
    11.スマートポインタ
    shared_ptrは、複数のポインタが同じオブジェクトを指すことを許可し、unique_ptr独占が指すオブジェクト、weak_ptrはshared_を指す弱い参照ですptrが管理するオブジェクト
  • shared_ptrとunique_ptrがサポートするオペレーション
  • shared_ptr<T> p; //     ,       T   
    unique_ptr<T> p;
    p; // p        , p      ,  true
    *p; //   p        
    p->get(); //  p      。     ,                ,           
    swap(p,q); //  p、q    
    p.swap(q);
    
    
  • shared_ptr他の方法
  • shared_ptr<T> p(q) //p      q     ; q    new     ,      T*  
    shared_ptr<T> p(u) //p unique_ptr u            ; u   
    shared_ptr<T> p(q,d) //p       q          ;q      T*  。p         d   delete
    shared_ptr<T> p(p2,d) //p shared_ptr p2   ,      p   d   delete
    p.reset(); // p         shared_ptr,reset      。
    p.reset(q); //            q,  p  q,    p  
    p.reset(q.d); //       d,    d   delete   q
    
  • 初期化:
  • //        
    shared_ptr<string> print(new string("normal usage!"));
    cout<<*print<<endl;
    
    //           
    shared_ptr<string> print1 = make_shared<string>("safe usage!");
    cout<<*print1<<endl;
    
  • get()関数
  • インテリジェントポインタが管理するオブジェクトを指す内蔵ポインタを返します.
    設定の目的は、スマートポインタを使用できないコードに内蔵ポインタを渡すことです.
    getを使用してポインタを返すコードはdeleteというポインタを使用できません.
    栗:
    shared_ptr<int> p1 = make_shared<int>(32);
    cout<<*(p.get())<<endl;
    shared_ptr<string> s = make_shared<string>("hhhhhha"); 
    //       auto s = make_shared("hhhhhha");
    cout<<*(s.get())<<endl;
    
    //     
    shared_ptr<int>p2(p1.get()); //p1、p2               ,           ,       
    delete (p1.get)//error!
    
    
  • shared_ptrのコピーと付与参照カウンタuse_count();
  • auto p = make_shared<int>(42); //p       p     
    cout<<p.use_count()<<endl;                                         //1
    auto q(p); //p q       ,         
    cout<<p.use_count()<<endl;                                         //2
    auto r = make_shared<int>(56); //       r     
    cout<<r.use_count()<<endl;                                         //1
    r = p; //r                 ,p      p、q、r    
    cout<<*p<<"=="<<*q<<"=="<<*r;                                      //42==42==42
    count<<p.use_count()<<endl;                                        //3
    count<<q.use_count()<<endl;                                        //3
    count<<r.use_count()<<endl;                                        //3
    

    r = p;//r元の参照のオブジェクトは付与された後に解放され,直接新しい参照を指す.
  • コンテナのshared_ptrはereaseでメモリを節約することを覚えています
  • メモリの場合shared_ptrはshared_がある限り保証します.ptrオブジェクトがそれを参照すると、彼は解放されません.
    -この特性のためshared_ptrは、使用しない後に保持されない非常に重要であり、通常、このプロセスは自動的に実行され、人工的な介入は必要ありませんが、shared_ptrは容器に入っています.だからereaseが使わないsharedを忘れないでください.pte
  • std::enable_shared_from_this

  • いずれかのオブジェクト(tという名前でstd::shared_ptrオブジェクトptによって管理されていると仮定)に、他の追加のstd::shared_ptrインスタンス(pt 1,pt 2,...)を安全に生成させ、ptとオブジェクトtの所有権を共有させることができる
    クラスTがstd::enable_shared_from_thisを継承すると、クラスTにメンバー関数が提供される:shared_from_thisT型オブジェクトtがptと命名するstd::shared_ptrクラスのオブジェクトによって管理されると、T::shared_from_thisメンバー関数を呼び出すと、ptとtの所有権を共有する新しいstd::shared_ptrオブジェクトが返されます.
    不足の後は補充中