c++FAQまとめ_ダイナミック配列

8223 ワード

ダイナミック配列
c++言語と標準ライブラリは、1つのオブジェクト配列を一度に割り当てる2つの方法を提供します.1.オブジェクト配列を割り当てて初期化できるnew式.2、提供されたallocatorクラスは、割り当てと初期化を分離することができます.コンテナのクラスを使用すると、デフォルトのバージョンのコピー、割り当て、およびプロファイル操作を使用できます.動的配列を割り当てるクラスでは、オブジェクトのコピー、コピー、破棄時に関連するメモリを管理する独自のバージョンの操作を定義する必要があります.
newと配列newにオブジェクト配列を割り当てるには、タイプ名の後にカッコを付けて、割り当てるオブジェクトの数を指定します(定数ではなく整数でなければなりません).
int *pia=new int[getsize()];//pia     int

typedef int art[42];
int *p=new art;

配列を割り当てると、要素タイプのポインタが得られます.割り当てられたメモリは配列タイプではないため、動的配列に対してbeginまたはendを呼び出すことはできません.これらの関数は、配列次元(次元は配列タイプの一部)を使用して、先頭要素と末尾要素を指すポインタを返します.同じ理由で、範囲for文を使用して(いわゆる)動的配列内の要素を処理することはできません.
  • 動的割り当てオブジェクトの配列
  • を初期化する.
    Newで割り当てられたオブジェクトは、単一の割り当てでも配列でもデフォルトで初期化されます.値で初期化するか、要素初期化器のカッコリストを指定できます.
    int*pia=new int[10];//               ,     
    int*pia2=new int[10]();//    
    string *psa=new string[10];//  string
    string *psa2=new string[10]();
    
    int *pia3 =new int[10]{1,2,3,4,5,6,7,8,9,10};
    
    string *psa3=new string[10]{"a","an","the",string(3,'x')};
    //10 string,              ,         。

    NOTE:配列内の要素をカッコで初期化できますが、カッコで初期化器を与えることはできません.したがって、動的メモリとスマートポインタのように、メモリを直接管理するときにautoで動的配列を割り当てることはできません.
    特殊:空の配列を動的に割り当てるのは合法です.0のサイズの静的配列オブジェクトを作成することはできませんが、nが0の場合、new[n]を呼び出すのは合法です.
    char arr[0];//  
    char *cp=new char[0];//  ,       
  • 動的配列
  • を解放する
    delete []pa;//pa                。

    paが指す配列の要素を破棄し、対応するメモリを解放します.配列内の要素は逆順序で破棄されます.配列を指すポインタをdeleteで無視した場合(または、単一のオブジェクトを指すポインタに角カッコを使用した場合)、その動作は定義されていません.
  • インテリジェントポインタと動的配列標準ライブラリは、new割り当てられた配列を管理できるunique_を提供します.ptrバージョン.
  • unique_ptr<int[]> up(new int[10]);
    up.release();//   delete[]     。

    配列を指すunique_ptrの操作
       unique_ptr                        
    
    unique_ptr[]>u;
    unique_ptr[]>u(p);  //u      p           。
    u[i];

    NOTE:shared_ptrは動的配列の管理をサポートしません.自分で定義する必要がある削除器を使用し、下付き演算をサポートしない場合は、通常get()で要素にアクセスします.
    shared_ptr<int> sp(new int[10],[](int *p){delete[] p;});
    sp.reset();
    //       lambda    ,  delete[]
    //                 ,   shared_ptr    delete,    delete               []  。
    
    for(size_t i=0;i!=0;++i)
        *(sp.get()+i)=i;//        ,               。  ,  get()         。

    allocatorクラスnewにはいくつかの柔軟性の限界があり、その1つはメモリ割り当てとオブジェクト構造を組み合わせたものであり、deleteはオブジェクトプロファイルとメモリ解放を組み合わせたものである.大きなメモリを割り当てると、通常、このメモリにオブジェクトをオンデマンドで構築する計画です.この場合、メモリ割り当てとオブジェクト構造を分離します.すなわち、オブジェクト作成操作は、本当に必要なときにのみ実行できる大きなメモリを割り当てることができます.さらに重要なのは、デフォルトのコンストラクション関数(デフォルトの初期化と値の初期化ができない)がないクラスは、配列を動的に割り当てることができません.allocatorクラスは、メモリ割り当てとオブジェクト構造を分離するのに役立ち、割り当てられたメモリは元の未構築です.
    allocatorクラスはテンプレートクラスで、allocatorオブジェクトがメモリを割り当てると、指定したオブジェクトタイプに基づいて適切なメモリサイズとその位置が決定されます.サポートされるアクション:
    #include 
    //      a allocator  ,       T       
    allocator a;
    
    //       、      ,  n    T   。
    a.allocate(n)
    
    /*     p        ,       n    T   ;
    p        allocate     , n   p         。
       deallocate  ,                    destroy*/
    a.deallocate(p,n);
    
    // p          ,arg          
    a.construct(p,args);
    
    // p           
    a.destroy(p);

    example:
    allocator<string> alloc;
    auto const p=alloc.allocate(n);
    
    auto q=p;//              
    alloc.construct(q++);//*q     
    alloc.construct(q++,10,'c');
    alloc.construct(q++,"hi");
    cout<//
    cout<//            
    while(q!=p){
        alloc.destroy(--q);//       string                        string
    }
    alloc.deallocate(p,n);//       

    allocateで返されるメモリを使用するには、constructを使用してオブジェクトを構築する必要があります.未構築のメモリ動作を使用することは定義されていません.エレメントオブジェクトを使い切った後、各コンストラクションのエレメントに対してdestroyを呼び出して破棄する必要があります(本当に構築されたエレメントに対してdestroy操作しかできません).エレメントが破棄されると、このメモリを再使用して同じタイプのエレメントを保存したり、システムに返したりすることができます.
  • allocatorアルゴリズムこのセクションでは、メモリのコピーと初期化のためのallocatorクラスの2つの付随アルゴリズムについて説明します.
  • /*               ,             */
    
    
    /*    b e                b2            。
    b2          ,              。*/
    uninitialized_copy(b,e,b2);
    
    //    b       ,  n    b2      
    uninitialized_copy_n(b,n,b2);
    
    //    b e              ,      t   
    uninitialized_fill(b,e,t);
    
    //    b           n   。b                ,           
    uninitialized_fill_n(b,n,t);
    
    
    /*     vector           */
    
        allocator<int> alloc;
        auto p=alloc.allocate(v.size()*2);
        //       ,               
        auto q=uninitialized_copy(v.begin(),v.end(),p);
        //        42
        uninitialized_fill_n(q,v.size(),42);