## 4.2 ファセットの寿命

前節の `mythical` の例では、演算子 `new` で 2 つのファセットオブジェクトを作成し、ロケールに組み込みましたが、演算子 `delete` による削除はまだ行っていません。一般のオブジェクトの場合には良いコーディングではありませんが、ファセットオブジェクトに関しては正しいプログラムです。ファセットをロケールに組み込んだ後は、それが不要になったときの削除はロケールシステムによって行われます。つまり、そのファセットに対する参照を含むロケールがなくなったときが、そのファセットが不要になったときとなります。

この機能の便利さを説明するために、次に例を挙げます。

>     cout.imbue(locale(locale(),new numpunct_byname<char>("de_DE")));
>          |     |      |        |
>         (4)   (3)    (1)      (2)

この処理はきわめて複雑なので、段階を追って確認します。

1. 現在の大域ロケールのコピーである一時ロケールオブジェクトを作成します。
2. ドイツ語ロケールに `numpunct` ファセットを作成します。
3. `(1)` で作成した一時ロケールの別のコピーを作成しますが、その `numpunct` ファセットは `(2)` で作成したファセットに置き換わります。
4. 一般のコンパイラでロケールのコピーコンストラクタを使用して、このロケールを値ごとに `cout.imbue` に渡します。コピーがストリームオブジェクトに保存されます。

以上の動作が終了すると、一時オブジェクトはすべて自動的に削除されますが、新しい `numpunct` ファセットに対する参照は、`cout` 内のロケールオブジェクトに保存されます。`cout.getloc()` を使用することで、他の関数でこのオブジェクトを検索し、そのコピーとファセットを作成することができます。`numpunct_byname` オブジェクトをいつ安全に削除できるかを判断するために、以上のすべてをユーザーが追跡する必要があるとすると、それは適用の際に大変な負担になりますが、実際にはロケールシステムが代わりに行うため問題にはなりません。

このデフォルトの設定を無効にすることもできますが、推奨しません。すべての標準ファセットのコンストラクタと、基底クラス `locale::facet` のコンストラクタは、いずれも `refs` という名の整数パラメータを使用し、指定しない場合はデフォルトでゼロになります。これは一般的なことです。`1` や他の正の整数を指定すると、ロケールシステムではファセットは削除されません。

たとえば、スタック上やスタックオブジェクトとして作成された場合など、`delete` 演算子を使用できないファセットオブジェクトには必要な機能です。このようなファセットを偶発的に作成してしまうことを防ぐために、標準ファセットには保護デストラクタがあります。たとえば、次のコードはコンパイルエラーになります。

>     static numpunct<char> my_static_np(1);     // エラー: 公開デストラクタはない

>     int main () {
>       numpunct_byname<char> my_np("de_DE",1);  // エラー: 公開デストラクタはない
>       ...
>     }

この保護を回避するには、標準ファセットから公開デストラクタのあるクラスを派生させます。スタンドアロンオブジェクトとして使用して、ロケールに組み込む予定がない場合は、これで問題ありません。たとえば、次のコードでは `new/delete` を使用しなくても、標準 `numpunct<char>` ファセットからデータを検索することができます。

>     class my_numpunct: public numpunct<char> { };
>     int main () {
>       my_numpunct np;
>       cout << np.truename() << " or " << np.falsename() << '?' << endl;
>       ...
>     }

しかし、次のコードでは同じことをさらに短時間に処理することができます。これは、通常のファセットのコンストラクタを呼び出すよりも、`use_facet` の方がはるかに高速で処理できるためです。

>     int main () {
>       const numpunct<char> &np=
>           use_facet<numpunct<char> >(locale::classic());
>       cout << np.truename() << " or " << np.falsename() << '?' << endl;
>       ...
>     }

スタック上にファセットオブジェクトを作成することはできますが、現実にそれが必要な機会はほとんどありません。ファセットオブジェクトは、常に、演算子 `new` で作成するという一貫した方針を守る方がより適しています。ファセットをロケールに組み込むときに削除する必要がなく、また、実際に削除すればエラーになります。ロケールに組み込むことがなければ、終了時に削除すれば問題ありません。このようにして、スタンドアロンファセットの作成や削除をしなくても、一般にはロケールから既存のファセットに対する参照を検索することで、同じことを (そしてより短時間で) 処理することができます。

Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。

OEM リリース, 1998 年 6 月