バナーをクリックすれば目次に戻ります

Copyright 1999 Rogue Wave Software
Copyright 1999 Sun Microsystems, Inc.


RWTValVirtualArray<T>

形式

#include <rw/tvrtarry.h>
RWVirtualPageHeap* heap;
RWTValVirtualArray<T> array(1000L, heap);

説明

このクラスは、ほとのど無制限な長さの型 T の要素から成る仮想配列を表します。個々の要素は必要に応じて物理メモリーに書き込まれます。ある要素が更新された場合、その要素は自動的に "変更済み (dirty)" の印が付けられ、スワップ媒体に再度書き込まれます。

スワップ領域は、コンストラクタが指定する抽象ページヒープによって提供されます。任意の数の仮想配列で、同一の抽象ページヒープを使用できます。その抽象ページヒープから構築された仮想配列をすべて破壊してからでないと、抽象ページヒープのデストラクタを呼び出すことはできません。

このクラスは、書き込み時コピーの技法を使用して参照カウントをサポートしているので、関数から値によって仮想配列を返す処理などは非常に効率良く行われます。しかし、書き込み時コピーの技法も結局コピーを行う必要があり、大きな仮想配列の場合にはかなり時間がかかります。

効率を上げるためには、複数の要素を 1 ページに設定するとよいでしょう。実際の要素数は、ページサイズを要素サイズで割って余りを切り捨てたものになります。たとえば、ページサイズが 512 バイトで要素サイズが 8 バイトの場合は、1 ページに 64 要素割り当てられることになります。

インデックス付け演算子 (operator[](long)) は、型 RWTVirtualElement<T> のオブジェクトを返します。

double d = vec[j];
vec[i] = 22.0;
上記の例で、vec は型 RWTValVirtualArray<double> であるとします。式 vec[j] は型 RWTVirtualElement<double> のオブジェクトを返します。これはアドレスを指定された要素への参照を含んでいます。1 行目では double を初期化しています。クラス RWTVirtualElement<T> には、自分自身を T (この場合、double) に変換する型変換演算子があります。コンパイラはこれを使用して d を初期化します。

2 行目では、式 vec[i] を左辺値として使用しています。この場合、コンパイラは型 RWTVirtualElement<T> の代入演算子を使用します。この代入演算子はこの式が左辺値として使用されていることを認識し、自動的に該当ページに "変更済み (dirty)" の印を付けます。これによって、そのページがスワップ媒体に書き戻されることが保証されます。

個々の要素だけでなく、スライスもアドレス指定できます。スライスではページをアンロックする前に複数回ロックして使用できるため、非常に効率的です。

クラス T には、次のものが必要です。

また、要素のアドレスを直接使用してはいけません。

持続性

なし

次の例は、型 ErsatzInt のオブジェクトから成る仮想ベクトルを処理しています。ディスクベースのページヒープをスワップ領域に使用しています。

#include <rw/tvrtarry.h>
#include <rw/rstream.h>
#include <rw/diskpage.h>
#include <stdlib.h>
#include <stdio.h>

struct ErsatzInt {
  char  buf[8];
  ErsatzInt(int i) { sprintf(buf, "%d", i); }
  friend ostream& operator<<(ostream& str, ErsatzInt& i)
    { str << atoi(i.buf); return str; }
};

main() {
  RWDiskPageHeap heap;
  RWTValVirtualArray<ErsatzInt> vec1(10000L, &heap);

  for (long i=0; i<10000L; i++)
    vec1[i] = i;    // コンパイラによってはここでキャストを必要とする

  cout << vec1[100] << endl;    // "100" を出力する
  cout << vec1[300] << endl;    // "300" を出力する

  RWTValVirtualArray<ErsatzInt> vec2 = vec1.slice(5000L, 500L);
  cout << vec2.length() << endl;    // "500" を出力する
  cout << vec2[0] << endl;  // "5000" を出力する;

  return 0;
}

プログラム出力:

100
300
500
5000

公開コンストラクタ

RWTValVirtualArray<T>(long size, RWVirtualPageHeap* heap);

長さ size のベクトルを作成します。ベクトルのページは任意の型の heap で指定されたページヒープから割り当てられます。

RWTValVirtualArray<T>(const RWTValVirtualArray<T>& v);

ベクトルを v のコピーとして作成します。作成されるベクトルは v と同じヒープを使用し、同じ長さです。実際のコピーは書き込み時まで行われません。これによって、ヒープ割り当てとコピーの合計量が最小化されます。

RWTValVirtualArray<T>(const RWTVirtualSlice<T>& sl);

他のベクトルのスライスからベクトルを作成します。作成されるベクトルは、スライスを取られたベクトルと同じヒープを使用します。ベクトルの長さはスライスの長さで決まります。この場合、コピーは直ちに行われます。

公開デストラクタ

~RWTValVirtualArray<T>();

ベクトルに割り当てられたすべてのページを解放します。

公開演算子

RWTValVirtualArray&
operator=(const RWTValVirtualArray<T>& v);

自分自身に v のコピーを設定します。構築されるベクトルは v と同じヒープを使用し、同じ長さです。実際のコピーは書き込み時まで行われません。これによって、ヒープ割り当てとコピーの合計量が最小化されます。

void
operator=(const RWTVirtualSlice<T>& sl);

自分自身に他のベクトルのスライスを設定します。構築されるベクトルは、スライスを取られたベクトルと同じヒープを使用します。ベクトルの長さはスライスの長さで決まります。この場合、コピーは直ちに行われます。

T
operator=(const T& val);

自分自身内のすべての要素に val を設定します。この演算子は、単一ページの数多くの要素を一度に処理できるので、非常に効率的です。val のコピーを返します。

T
operator[](long i) const;

インデックス i の値のコピーを返します。インデックス i は 0 〜 (ベクトル長 -1) の範囲になければなりません。範囲外にあると TOOL_LONGINDEX 型の例外が発生します。

RWTVirtualElement<T>
operator[](long);

インデックス i の値への参照を返します。結果は左辺値として使用できます。インデックス i は 0 〜 (ベクトル長 -1) の範囲になければなりません。範囲外にあると TOOL_LONGINDEX 型の例外が発生します。

公開メンバー関数

long
length() const;

ベクトル長を返します。

T
val(long i) const;

インデックス i の値のコピーを返します。インデックス i は 0 〜 (ベクトル長 -1) の範囲になければなりません。範囲外にあると TOOL_LONGINDEX 型の例外が発生します。

void
set(long i, const T& v);

インデックス i の値を v に設定します。インデックス i は 0 〜 (ベクトル長 -1) の範囲になければなりません。範囲外にあると TOOL_LONGINDEX 型の例外が発生します。

RWTVirtualSlice<T>
slice(long start, long length);

自分自身のスライスへの参照を返します。値 start はスライスの開始インデックス、値 length はスライスの長さです。結果を左辺値として使用できます。

void
reshape(long newLength);

ベクトルの長さを newLength に変更します。この結果ベクトル長が長くなると、新しい要素の値は不定になります。

RWVirtualPageHeap*
heap() const;

ベクトルがページを得たヒープへのポインタを返します。