No.001-02
|
前回のリスト構造XLISTは定数をそのままリスト化するには非常に便利なのですが、
クラスをリスト化する場合には問題があり、
常にリストには引数のコピーであって引数そのものでない部分と、XLISTのdelete時に強制的にデストラクタが発生してしまうのです。
これの対策にはコピーコンストラクタをしっかり作ればいいのですが、毎回すべてのクラスに行うのは大変ですし、
第一、メモリの有効活用や、速度的なことを考えるならあまり良い方法ではありません。
そこで例えば class AAA のリストを作る場合
XLIST<AAA*> aaa_list;
として AAAのポインタでリスト化すればスッキリ解決です。
リストにはクラスのポインタが入ってるだけなのでデストラクタは発生しないのです。
XLIST<AAA*> aaa_list;
AAA *p_aaa;
p_aaa = new AAA;
aaa_list.push(p_aaa);
……
aaa_list.pop(n);
delete p_aaa;
まあこのまま使ってもいいんですが、本当にデストラクタが自動でないのも不便。
ついでにnew演算も自動化したいってコトで新テンプレートを作成。
PLIST(ポインタ・リスト)。
自動でnew と delete する。ポインタのリスト。deleteしない設定も可能。
基本的にはXLIST<クラス名*>的な概念で形成し、それをちょっと拡張した感じ。
使い方はシンプル | |
PLIST<クラス名> 変数名; | ・・・宣言(内部でXLIST<クラス名*>を宣言している) |
push(アイテムポインタ); | ・・・アイテムへのポインタをリストに追加 |
a_push(void) | ・・・内部でnew でメモリを確保し、そのポインタをリストに追加 |
pop(n); | ・・・n番目のアイテムをリストから削除 |
変数名[n]; | ・・・配列的にアクセス |
size(); | ・・・現在のアイテム数の取得 |
plist.h |
#ifndef _PLIST_H_ #define _PLIST_H_ #include <stdio.h> #include <stdlib.h> #include "xlist.h" //========================================== // PLIST ポインタ・リスト //========================================== template <class T> class PLIST { char destruct_flag; XLIST<T*> xlist; // has a型(多態push作成のためis aでない) public : // n1番目とn2番目のアイテムを交換する(swap) swap(int n1, int n2){ T* tmp_t=xlist[n1]; xlist[n1]=xlist[n2]; xlist[n2]=tmp_t; }; // 最後のアイテム(参照)を返す T* &last(){ return xlist.last(); }; // アイテム数を返す(len, size で同じもの) len(){ return xlist.size(); }; size(){ return xlist.size(); }; // リサイズ resize(int n){ int old_size=size(); // 旧サイズの保持 int res=xlist.resize(n); // メンバxlistでリサイズ実行 int i; if (old_size<size()){ for(i=old_size;i<size();i++) xlist[i]=a_push(); // 追加した分だけメモリ確保 } return res; }; // pop時アイテムのdeleteしないよう設定する set_no_destruct(){ return destruct_flag=0; } // コンストラクタ PLIST(){ destruct_flag=1; // pop時アイテムのdelete(アイテムのデストラクタが走る) T *t=NULL; // デフォルト値はNULL xlist.set_default(t); // デフォルト値はNULLであることをxlistに設定 }; // デストラクタ ~PLIST(){ del_all(); }; // オート・プッシュ T *a_push(int n=-1){ T* pt = new T; if (n==-1) xlist.push(pt); // n==-1ならアイテムは末尾に追加 else xlist.push(pt, n); // n が範囲内ならアイテムはn番目に挿入 // 返り値 return (n==-1)? last() : xlist[n]; } // アイテム追加(通常プッシュ) // 引数 t : 値、 n : 挿入位置 T *push(T &t, int n=-1){ T* pt = new T; *pt=t; if (n==-1) xlist.push(pt); // n==-1ならアイテムは末尾に追加 else xlist.push(pt, n); // n が範囲内ならアイテムはn番目に挿入 // 返り値 return (n==-1)? last() : xlist[n]; } // ポインタ引数でアイテム追加 // 引数 t : 値、 n : 挿入位置 p_push(T *t=NULL, int n=-1){ if (!t) t = new T; if (n==-1) xlist.push(t); else xlist.push(t, n); return 0; }; // 第n番目のアイテム削除 pop(int n=-1){ if (destruct_flag) delete xlist[n]; xlist[n]=NULL; xlist.pop(n); return 0; }; // tの値と同じアイテムの削除 val_pop(T *t){ return xlist.val_pop(t); } // ランダムアクセス T* &operator [](int n){ return xlist[n]; }; // 第n1番目のアイテムを第n2番目に移動 roll(int n1, int n2){ return xlist.roll(n1, n2); } // 全アイテム削除 del_all(){ int i, del_len=xlist.size(); for(i=del_len-1;i>=0;i--) pop(i); return 0; } }; #endif // _PLIST_H_ |
●PLIST サンプル |
#include "plist.h" int main(){ PLIST<int> list; // int型のポインタ・リストを宣言 int n=100, *pn; pn=list.a_push(); // アイテムを追加しそのアイテムへのポインタを得る *pn=n++; // 追加したアイテムに値を代入 pn=list.a_push();*pn=n++; pn=list.a_push();*pn=n++; pn=list.a_push();*pn=n++; pn=list.a_push();*pn=n++; pn=list.a_push();*pn=n++; list.pop(3); // list[3]をリストから削除 for(int i=0;i<list.size();i++){ printf("list[%d]=%d\n", i, *list[i]); // list[i]を表示 } printf("list.size(); %d\n", list.size()); // リストアイテム数を表示 list.del_all(); // アイテムの全削除。 printf("list.del_all();呼び出し \n"); printf("list.size(); %d\n", list.size()); // リストアイテム数を表示 list.resize(4); // アイテムの数を4個にする printf("list.size(); %d\n", list.size()); // リストアイテム数を表示 return 0; } |
実行結果 |
●PLIST サンプル2 |
#include "plist.h" #include <string> class AAA{ public: char *m_name; AAA(){ m_name=NULL; } ~AAA(){ if (m_name) delete[] m_name; } void cpy(char *str){ if (!str) return; m_name = new char[strlen(str)+1]; strcpy(m_name, str); } }; int main(){ int n=100; PLIST<AAA> aaa_list; // AAA型のポインタ・リストを宣言 AAA *p_aaa; p_aaa=aaa_list.a_push(); // アイテムを追加しそのアイテムへのポインタを得る p_aaa->cpy("アルファベット"); // 追加したアイテムに値を代入 p_aaa=aaa_list.a_push(); p_aaa->cpy("AB"); p_aaa=aaa_list.a_push(); p_aaa->cpy("CDE"); p_aaa=aaa_list.a_push(); p_aaa->cpy("FGHI"); p_aaa=aaa_list.a_push(); p_aaa->cpy("JKLMN"); p_aaa = new AAA; // 自分で new 演算してもいい。 aaa_list.p_push(p_aaa); p_aaa->cpy("OPQR"); // 自分でnewした時は a_push でなく p_push p_aaa=aaa_list.a_push(); p_aaa->cpy("STU"); p_aaa=aaa_list.a_push(); p_aaa->cpy("VW"); p_aaa=aaa_list.a_push(); p_aaa->cpy("XYZ"); aaa_list.pop(2); // aaa_list[2] をリストから削除 aaa_list.pop(); // 末尾アイテムをリストから削除 for(int i=0;i<aaa_list.size();i++){ printf("aaa_list[%d]->m_name=%s\n", i, aaa_list[i]->m_name); // list[i]を表示 } printf("aaa_list.size(); %d\n", aaa_list.size()); // リストアイテム数を表示 aaa_list.del_all(); // アイテムの全削除、ただしメモリは解放しない。 printf("aaa_list.del_all();呼び出し \n"); printf("aaa_list.size(); %d\n", aaa_list.size()); // リストアイテム数を表示 aaa_list.resize(4); // アイテムの数を4個にする printf("aaa_list.size(); %d\n", aaa_list.size()); // リストアイテム数を表示 return 0; } |
実行結果 |
上記ソースは全て自由に改編して使ってかまいませんが必ず自己責任でね。