20.8.4 Sequence
固定長および可変長に関係なくIDLに指定したSequenceは,現在の長さおよび最大長を持つC++クラスにマッピングされます。固定長シーケンスの最大長は,そのシーケンスの型によって定義されます。C++コンストラクタが呼び出される際に可変長シーケンスの最大長を指定できます。プログラミングによって,現在の長さを変更できます。コードサンプル20-28〜20-29では,IDLシーケンスがアクセッサメソッドを含むC++クラスへとマッピングされています。
- 注
-
可変長シーケンスの長さが,指定した最大長よりも長い場合,Borland Enterprise Server VisiBrokerは,バッファが大きい方を透過的に割り当てます。その際,古いバッファが新しいバッファへとコピーされ,その古いバッファに割り当てられていたメモリが解放されます。しかし,最大長が減ると,使用されなかったメモリは解放されません。
- コードサンプル20-28 IDL可変長シーケンス
// IDL typedef sequence<long> LongSeq;
- コードサンプル20-29 IDL可変長シーケンスのC++クラスへのマッピング
// C++ class LongSeq { public: LongSeq(CORBA::ULong max=0); LongSeq(CORBA::ULong max=0, CORBA::ULong length, CORBA::Long *data, CORBA::Boolean release = 0); LongSeq(const LongSeq&); ~LongSeq(); LongSeq& operator=(const LongSeq&); CORBA::ULong maximum() const; void length(CORBA::ULong len); CORBA::ULong length() const; const CORBA::ULong& operator[ ]( CORBA::ULong index) const; ... static LongSeq *_duplicate(LongSeq* ptr); static void _release(LongSeq *ptr); static CORBA::Long *allocbuf(CORBA::ULong nelems); static void freebuf(CORBA::Long *data); private: CORBA::Long* _contents; CORBA::ULong _count; CORBA::ULong _num_allocated; CORBA::Boolean _release_flag; CORBA::Long _ref_count; };
コードサンプル20-29に示した可変長シーケンスのために生成されたメソッド一覧を次の表に示します。
メソッド |
説明 |
---|---|
LongSeq(CORBA::ULong max=0) |
可変長シーケンスのコンストラクタは,最大長を引数として使用します。固定長シーケンスには定義された最大長が含まれます。 |
LongSeq(CORBA::Ulong max=0, CORBA::ULong length, CORBA::Long *data, CORBA::Boolean release=0) |
コンストラクタで,最大長,現在の長さ,対応するデータバッファのポインタ,解放フラグを設定できます。releaseが0でない場合にシーケンスのサイズを拡大する際,データバッファに対応するメモリを解放します。releaseが0である場合,古いデータバッファのメモリは解放されません。固定長シーケンスでは,max以外のこれらすべてのパラメタを使用します。 |
LongSeq(const LongSeq&) |
コピーコンストラクタは,ソースオブジェクトのディープコピーを実行します。 |
~LongSeq(); |
解放フラグが構成された際に0以外の値を持つ場合だけ,デストラクタがシーケンスによって所有されるメモリを解放します。 |
operator=(const LongSeq&) |
代入演算子がディープコピーを実行します。必要な場合,古いメモリを解放します。 |
maximum() |
シーケンスのサイズを返します。 |
length() |
シーケンスの長さを設定したり,返したりするために,二つのメソッドが定義されます。 |
operator[ ] () |
シーケンス内の要素にアクセスするために二つのインデックス演算子が提供されています。一方はその要素を修正するための演算子で,もう一方は要素を読み込むためだけ(読み取り専用)の演算子です。 |
_release() |
シーケンスを解放します。オブジェクトが生成され,シーケンス要素型が文字列およびオブジェクトリファレンスである場合で,コンストラクタの解放フラグが0以外の値であるときは,バッファが解放される前に各要素が解放されます。 |
allocbuf() freebuf() |
シーケンス用のメモリを割り当てたり,解放したりするために,これら二つの静的メソッドを使用します。 |
- 〈この項の構成〉
(1) シーケンスの管理型
コードサンプル20-29に示したLongSeqクラスに加えて,LongSeq_varクラスも生成されます。_varの詳細については,「21.6 <class_name>_var」を参照してください。また,通常の_varメソッドに加えて,シーケンスのインデックスメソッドが二つ定義されています。
- コードサンプル20-30 シーケンスを表す_varクラスに追加された二つのインデックスメソッド
CORBA::Long& operator[ ](CORBA::ULong index); const CORBA::Long& operator[ ](CORBA::ULong index) const;
(2) シーケンスでのメモリ管理
メモリ管理をする際には,次の事項に注意してください。コードサンプル20-31〜20-32は,次の事項を配慮しています。
-
シーケンスが生成された際にその解放フラグが0以外の値で設定された場合,そのシーケンスがユーザのメモリの管理を引き受けます。要素が代入された際,右側にあるメモリの所有権が引き受けられる前に,古いメモリが解放されます。
-
文字列またはオブジェクトリファレンスを含むシーケンスが生成された際に,その解放フラグが0以外の値で設定された場合,シーケンスのコンテンツバッファが解放される前,およびそのオブジェクトがデストラクトされる前に,各要素が解放されます。
-
解放フラグに1が設定されていないかぎり,[ ]演算子を使ってシーケンス要素を代入しないでください。代入した場合,メモリ管理のエラーが発生するおそれがあります。
-
解放フラグに0を設定してシーケンスを生成した場合,そのシーケンスをinoutパラメタとして使用しないでください。オブジェクトサーバでメモリ管理のエラーが発生するおそれがあります。
-
シーケンスで使用するメモリを作成および解放する場合は,必ずallocbufおよびfreebufを使用してください。
- コードサンプル20-31 固定長シーケンスのIDL仕様
// IDL typedef sequence<string, 3> StringSeq;
- コードサンプル20-32 二つの固定長シーケンスでのメモリ管理の例
// C++ char *static_array[ ] = {(char*)"1", (char*)"2", (char*)"3"}; char **dynamic_array = StringSeq::allocbuf(3); dynamic_array[0] = CORBA::string_dup("1"); dynamic_array[1] = CORBA::string_dup("2"); dynamic_array[2] = CORBA::string_dup("3"); // シーケンスを作成し,解放フラグはデフォルトのFALSEを設定します。 StringSeq static_seq(3, static_array); // 別のシーケンスを作成し,解放フラグはTRUEを設定します。 StringSeq dynamic_seq(3, dynamic_array, 1); static_seq[1] = "1"; // 古い領域は,解放されないでコピーされます。 char *str = CORBA::string_dup("1"); dynamic_seq[1] = str; // 古い領域は,解放され代入されます。