ライブラリを使用すると、アプリケーション間でコードを共有したり、非常に大規模なアプリケーションを単純化できます。C++ コンパイラでは、さまざまなライブラリを使用できます。この章では、これらのライブラリの使用方法を説明します。
Solaris オペレーティングシステムでは、いくつかのライブラリが /usr/lib にイン ストールされます。このライブラリのほとんどは C インタフェースを持っています。デフォルトでは libc および libm ライブラリが CC ドライバによってリンクされます。ライブラリ libthread は、-mt オプションを指定した場合にのみリンクされます。それ以外のシステムライブラリをリンクするには、-l オプションでリンク時に指定する必要があります。たとえば、libdemangle ライブラリをリンクするには、リンク時に -ldemangle を CC コマンド行に指定します。
example% CC text.c -ldemangle |
C++ コンパイラには、独自の実行時ライブラリが複数あります。すべての C++ アプリケーションは、CC ドライバによってこれらのライブラリとリンクされます。C++ コンパイラには、次の節に示すようにこれ以外にも便利なライブラリがいくつかあります。
Sun C++ コンパイラには、いくつかのライブラリが添付されています。 これらのライブラリには、互換モード (-compat=4) だけで使用できるもの、標準モード (-compat=5) だけで使用できるもの、あるいは両方のモードで使用できるものがあります。libgc ライブラリと libdemangle ライブラリには C インタフェースがあり、どちらのモードでもアプリケーションにリンクできます。
次の表に、Sun C++ コンパイラに添付されるライブラリと、それらを使用できるモードを示します。
表 12–1 C++ コンパイラに添付されるライブラリ
ライブラリ |
内容の説明 |
使用できるモード |
---|---|---|
libstlport |
標準ライブラリの STLport 実装 |
-compat=5 |
libstlport_dbg |
デバッグモード用 STLport ライブラリ |
-compat=5 |
C++ 実行時 |
-compat=5 |
|
C++ 標準ライブラリ |
-compat=5 |
|
従来の iostream |
-compat=5 |
|
C++ 実行時、従来の iostream |
-compat=4 |
|
-xia オプションをサポート |
-compat=5 |
|
複素数ライブラリ |
-compat=4 |
|
librwtool |
Tools.h++ 7 |
-compat=4、-compat=5 |
デバッグ可能な Tools.h++ 7 |
-compat=4,-compat=5 |
|
ガベージコレクション |
C インタフェース |
|
復号化 |
C インタフェース |
STLport、Rogue Wave、または Sun Microsystems C++ ライブラリの構成マクロを再定義したり変更したりしないでください。ライブラリは C++ コンパイラとともに動作するよう構成および構築されています。libCstd と Tool.h++ は互いに働き合うように構成されているので、その構成マクロを変更すると、プログラムのコンパイルやリンクが行われなくなったり、プログラムが正しく実行されなくなったりします。
これらのライブラリについて簡単に説明します。
libCrun: このライブラリには、コンパイラが標準モード (-compat=5) で必要とする実行時サポートが含まれています。new と delete、例外、RTTI がサポートされます。
libCstd: これは C++ 標準ライブラリです。特に、このライブラリには iostream が含まれています。既存のソースで従来の iostream を使用している場合には、ソースを新しいインタフェースに合わせて修正しないと、標準 iostream を使用できません。詳細は、オンラインマニュアルの『Standard C++ Library Class Reference』を参照してください。
コンパイラソフトウェアが /opt ディレクトリにインストールされていない場合は、システム上でこのディレクトリに相当するパスをシステム管理者に問い合わせてください。
libiostream: これは標準モード (-compat=5) で構築した従来の iostream ライブラリです。既存のソースで従来の iostream を使用している場合には、libiostream を使用すれば、ソースを修正しなくてもこれらのソースを標準モード (-compat=5) でコンパイルできます。このライブラリを使用するには、-library=iostream を使用します。
標準ライブラリのほとんどの部分は、標準 iostream を使用することに依存しています。従来の iostream を同一のプログラム内で使用すると、問題が発生する可能性があります。
libC: これは互換モード (-compat=4) で必要なライブラリです。このライブラリには C++ 実行時サポートだけでなく従来の iostream も含まれています。
libcomplex: このライブラリは、互換モード (-compat=4) で複素数の演算を行うときに必要です。標準モードの場合は、libCstd の複素数演算の機能が使用されます。
libstlport: これは、C++ 標準ライブラリの STLport 実装です。このライブラリを使用するには、デフォルトの libCstd の代わりにオプション -library=stlport4 を指定します。ただし、libstlport と libCstd の両方を同一プログラム内で使用することはできません。インポートしたライブラリを含み、すべてをどちらか一方のライブラリだけを使ってコンパイルしリンクする必要があります。
librwtool (Tools.h++): Tools.h++ は、RogueWave の C++ 基礎クラスライブラリです。Version 7 が提供されています。このライブラリは廃止され、新しいコードでこのライブラリを使用することは非推奨です。RW Tools.h++ を使用していた、C++ 4.2 用に作成されたプログラムに対応する目的で、このライブラリは提供されています。
libgc: このライブラリは、展開モードまたはガベージコレクションモードで使用します。libgc ライブラリにリンクするだけで、プログラムのメモリーリークを自動的および永久的に修正できます。プログラムを libgc ライブラリとリンクする場合は、free や delete を呼び出さずに、それ以外は通常どおりにプログラムを記述できます。ガベージコレクションライブラリは、動的読み込みライブラリと依存関係があるため、プログラムのリンクでは、-lgc および -ldl を指定します。
詳細については、gcFixPrematureFrees(3) および gcInitialize(3) のマニュアルページを参照してください。
libdemangle: このライブラリは、C++ 符号化名を復号化するときに使用します。
この節で説明しているライブラリに関するマニュアルページは1、3、3C++、および 3cc4 の各節にあります。
C++ ライブラリのマニュアルページにアクセスするには次のとおり入力してください。
example% man library-name |
C++ ライブラリの Version 4.2 のマニュアルページにアクセスするには次のコマンドを入力してください。
example% man -s 3CC4 library-name |
これらのライブラリには、CC ドライバによってデフォルトでリンクされるものと、明示的にリンクしなければならないものがあります。標準モードでは、次のライブラリが CC ドライバによってデフォルトでリンクされます。
互換モード (-compat) では、次のライブラリがデフォルトでリンクされます。
-lC -lm -lc
詳細は、「A.2.50 -library=l[ ,l...]」 を参照してください。
CC ドライバには、ライブラリを使用するためのオプションがいくつかあります。
マルチスレッド化コードをコンパイルしてリンクするには、-mt オプションを使用します。
区間演算ライブラリをリンクするには、-xia オプションを使用します。
Fortran または C99 実行時ライブラリをリンクするには、-xlang オプションを使用します。
Sun C++ コンパイラに添付された次のライブラリを指定するには、-library オプションを使用します。
libCrun
libCstd
libiostream
libC
libcomplex
libstlport、libstlport_dbg
librwtool、librwtool_dbg
libgc
librwtool の従来の iostream 形式を使用するには、-library=rwtools7 オプションを使用します。librwtool の標準 iostream 形式を使用するには、-library=rwtools7_std オプションを使用します。
-library オプションと -staticlib オプションの両方に指定されたライブラリは静的にリンクされます。次にその例を挙げます。
次のコマンドでは Tools.h++ Version 7 の従来の iostream 形式と libiostream ライブラリが動的にリンクされます。
example% CC test.cc -library=rwtools7,iostream |
次のコマンドでは libgc ライブラリが静的にリンクされます。
example% CC test.cc -library=gc -staticlib=gc |
次のコマンドでは test.cc が互換モードでコンパイルされ、libC が静的にリンクされます。互換モードでは libC がデフォルトでリンクされるので、このライブラリを -library オプションで指定する必要はありません。
example% CC test.cc -compat=4 -staticlib=libC |
次のコマンドでは ライブラリ libCrunおよび libCstd がリンク対象から除外されます。指定しない場合は、これらのライブラリは自動的にリンクされます。
example% CC test.cc -library=no%Crun,no%Cstd |
デフォルトでは、CC は、指定されたコマンド行オプションに従ってさまざなシステムライブラリをリンクします。-xnolib (または -nolib) を指定した場合、CC は、-l オプションを使用してコマンド行で明示的に指定したライブラリだけをリンクします。-xnolib または -nolib を使用した場合、-library オプションが存在していても無視されます。
-R オプションは、動的ライブラリの検索パスを実行可能ファイルに組み込むときに使用します。実行時リンカーは、実行時にこれらのパスを使ってアプリケーションに必要な共有ライブラリを探します。CC ドライバは、デフォルトで -R<install_directory/lib を ld に渡します (コンパイラが標準の場所にインストールされている場合)。共有ライブラリのデフォルトパスが実行可能ファイルに組み込まれないようにするには、-norunpath を使用します。
配備用に構築するプログラムは、コンパイラのディレクトリでライブラリを参照することを防止する -norunpath または -R オプションを使用して構築するべきです (「12.6 共有ライブラリの使用」を参照してください)。
一般に、クラスライブラリを使用するには 2 つの手順が必要です。
ソースコードに適切なヘッダーをインクルードする。
プログラムをオブジェクトライブラリとリンクする。
C++ コンパイラには、2 通りの iostream が実装されています。
従来の iostream。この用語は、C++ 4.0、4.0.1、4.1、4.2 コンパイラに添付された iostream ライブラリ、およびそれ以前に cfront ベースの 3.0.1 コンパイラに添付された iostream ライブラリを指します。このライブラリの標準はありませんが、既存のコードの多くがこれを使用しています。このライブラリは、互換モードの libC の一部であり、標準モードの libiostream にもあります。
標準の iostream。これは C++ 標準ライブラリ libCstd に含まれていて、標準モードだけで使用されます。これは、バイナリレベルでもソースレベルでも「従来の iostream」とは互換性がありません。
すでに C++ のソースがある場合、そのコードは従来の iostream を使用しており、次の例のような形式になっていると思われます。
// file prog1.cc #include <iostream.h> int main() { cout << "Hello, world!" << endl; return 0; } |
次のコマンドは、互換性モードで prog1.cc をコンパイル、リンクして、prog1 という実行可能なプログラムを生成します。従来の iostream ライブラリは、互換性モードのときにデフォルトでリンクされる libC ライブラリに含まれています。
example% CC -compat prog1.cc -o prog1 |
次の例では、標準 iostream が使用されています。
// file prog2.cc #include <iostream> int main() { std::cout << "Hello, world!" << std::endl; return 0; } |
次のコマンドは、prog2.cc をコンパイル、リンクして、prog2 という実行可能なプログラムを生成します。コンパイルは標準モードで行われ、このモードでは、標準の iostream ライブラリを含む libCstd がデフォルトでリンクされます。
example% CC prog2.cc -o prog2 |
libCstd についての詳細は、「警告:」を参照してください。libiostream の詳細は、「13.3.1 再配布とサポートされる STLport ライブラリ」を参照してください。
コンパイルモードの詳しい説明については、『C++ 移行ガイド』を参照してください。
標準ライブラリには、C++ 4.2 コンパイラに付属していた complex ライブラリに似た、テンプレート化された complex ライブラリがあります。標準モードでコンパイルする場合は、<complex.h> ではなく、<complex> を使用する必要があります。互換性モードで <complex> を使用することはできません。
互換性モードでは、リンク時に complex ライブラリを明示的に指定しなければなりません。標準モードでは、complex ライブラリは libCstd に含まれており、デフォルトでリンクされます。
標準モード用の complex.h ヘッダーはありません。C++ 4.2 では、「complex」 はクラス名ですが、標準 C++ では「complex」はテンプレート名です。したがって、旧式のコードを変更せずに動作できるようにする typedef を使用することはできません。このため、複素数を使用する、4.2 用のコードで標準ライブラリを使用するには、多少の編集が必要になります。たとえば、次のコードは 4.2 用に作成されたものであり、互換性モードでコンパイルされます。
// file ex1.cc (compatibility mode) #include <iostream.h> #include <complex.h> int main() { complex x(3,3), y(4,4); complex z = x * y; cout << "x=" << x << ", y=" << y << ", z=" << z << endl; } |
次の例では、ex1.cc を互換モードでコンパイル、リンクし、生成されたプログラムを実行しています。
example% CC -compat ex1.cc -library=complex example% a.out x=(3, 3), y=(4, 4), z=(0, 24) |
次は、標準モードでコンパイルされるように ex2.cc と書き直された ex1.cc です。
// file ex2.cc (ex1.cc rewritten for standard mode) #include <iostream> #include <complex> using std::complex; int main() { complex<double> x(3,3), y(4,4); complex<double> z = x * y; std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl; } |
次の例では、書き直された ex2.cc をコンパイル、リンクして、生成されたプログラムを実行しています。
% CC ex2.cc % a.out x=(3,3), y=(4,4), z=(0,24) |
複素数演算ライブラリの使用方法についての詳細は、表 14–4 を参照してください。
次の表は、C++ ライブラリにリンクするためのコンパイラオプションをまとめています。詳細は、「A.2.50 -library=l[ ,l...]」を参照してください。
表 12–2 C++ ライブラリにリンクするためのコンパイラオプション
ライブラリ |
コンパイルモード |
オプション |
---|---|---|
-compat=5 |
不要 -library=iostream |
|
complex |
-compat=4 -compat=5 |
-library=complex 不要 |
-compat=4 -compat=5 |
-library=rwtools7 -library=rwtools7_std |
|
デバッグ対応 Tools.h++ Version 7 |
-compat=4 -compat=5 |
-library=rwtools7_dbg -library=rwtools7_dbg,iostream -library=rwtools7_std_dbg |
-compat=4 -compat=5 |
-library=gc -library=gc |
|
STLport Version 4 |
-compat=5 |
-library=stlport4 |
STLport Version 4 デバッグ |
-compat=5 |
-library=stlport4_dbg |
デフォルト時、CC ドライバは、デフォルトライブラリの -llib オプションをリンカーに渡すことによって、libc と libm を含むいくつかのライブラリの共有バージョンでリンクします。互換性モードと標準モードにおけるデフォルトライブラリのリストについては、「12.2.3 デフォルトの C++ ライブラリ」を参照してください。
このようにデフォルトのライブラリを静的にリンクする場合、-library オプションと -staticlib オプションを一緒に使用すれば、C++ ライブラリを静的にリンクできます。この方法は、以前説明した方法よりもかなり簡単です。たとえば、次のようにします。
example% CC test.c -staticlib=Crun |
この例では、-library オプションが明示的にコマンドに指定されていません。標準モード (デフォルトのモード) では、-library のデフォルトの設定が Cstd,Crun であるため、-library オプションを明示的に指定する必要はありません。
あるいは、-xnolib コンパイラオプションも使用できます。-xnolib オプションを指定すると、ドライバは自動的には -l オプションを ld に渡しません。次の例は、Solaris 8 または Solaris 9 オペレーティングシステムで libCrun と静的に、libm および libc と動的にリンクする方法を示します。
example% CC test.c– xnolib– lCstd– Bstatic– lCrun– Bdynamic– lm– lc |
-l オプションの順序は重要です。-lCstd、-lCrun、および -lm オプションは、-lc の前に表示します。
libCrun および libCstd を静的にリンクすることはお勧めできません。/usr/lib 内の動的バージョンは、インストール先の Solaris のバージョンで動作するよう構築します。
ほかのライブラリにリンクする CC オプションもあります。そうしたライブラリへのリンクも -xnolib によって行われないように設定できます。たとえば、-mt オプションを指定すると、CC ドライバは、-lthread を ld に渡します。これに対し、-mt と-xnolib の両方を使用すると、CC ドライバは ld に -lthread を渡しません。詳細は、「A.2.153 -xnolib」を参照してください。ld については、Solaris に関するマニュアル『リンカーとライブラリ』を参照してください。
/lib および /usr/lib にある Solaris ライブラリの静的バージョンは、もう使用できません。たとえば、libc を静的にリンクしようとする試みは、失敗します。
CC hello.cc -xnolib -lCrun -lCstd -Bstatic -lc |
次の C++ 実行時共有ライブラリは、C++ コンパイラの一部として出荷されています。
libCCexcept.so.1 (SPARC Solaris のみ)
libcomplex.so.5 (Solaris のみ)
librwtool.so.2
libstlport.so.1
Linux では、次の追加ライブラリが C++ コンパイラの一部として出荷されています。
libCrun.so.1
libCstd.so.1
libdemangle.so
libiostream.so.1
Solaris では、次の追加ライブラリがほかのライブラリとともに、C++ 実行時ライブラリパッケージである SUNWlibC の一部としてインストールされます。
アプリケーションが、C++ コンパイラの一部として出荷されている共有ライブラリのいずれかを使用している場合は、CC ドライバは runpath に調整を加え (-R オプションを参照)、実行可能ファイルの構築に使用するライブラリの場所を指すようにします。あとで、同じバージョンのコンパイラを同じ場所にインストールしていないコンピュータに実行可能ファイルを配備する場合は、必要な共有ライブラリが見つかりません。
プログラムの起動時に、ライブラリはまったく見つからない、あるいは誤ったバージョンのライブラリが使用される可能性があり、プログラムの正しくない動作につながります。このような状況では、必要なライブラリをプログラムと共に出荷し、それらのライブラリのインストール場所を指す runpath を指定して構築を行うべきです。
『Using and Redistributing Sun Studio Libraries in an Application』という資料には、このトピックに関する詳細な説明と例が掲載されていて、http://developers.sun.com/sunstudio/documentation/techart/stdlibdistr.html から入手できます。
ただし、コンパイラに添付された標準ライブラリを置き換えることは危険で、必ずしもよい結果につながるわけではありません。基本的な操作としては、コンパイラに添付されている標準のヘッダーとライブラリを無効にして、新しいヘッダーファイルとライブラリが格納されているディレクトリとライブラリ自身の名前を指定します。
コンパイラは、標準ライブラリの STLport 実装をサポートします。詳細は、「13.3 STLport」を参照してください。
ほとんどの標準ライブラリおよびそれに関連するヘッダーは置き換え可能です。置き換えるライブラリが libCstd である場合は、次の関連するヘッダーも置き換える必要があります。
<algorithm> <bitset> <complex> <deque> <fstream <functional> <iomanip> <ios> <iosfwd> <iostream> <istream> <iterator> <limits> <list> <locale> <map> <memory> <numeric> <ostream> <queue> <set> <sstream> <stack> <stdexcept> <streambuf> <string> <strstream> <utility> <valarray> <vector>
ライブラリの置き換え可能な部分は、いわゆる「STL」と呼ばれているもの、文字列クラス、iostream クラス、およびそれらの補助クラスです。このようなクラスとヘッダーは相互に依存しているため、それらの一部を置き換えるだけでは通常は機能しません。一部を変更する場合でも、すべてのヘッダーと libCstd のすべてを置き換える必要があります。
標準ヘッダー <exception>、<new>、および <typeinfo> は、コンパイラ自身とlibCrun に密接に関連しているため、これらを置き換えることは安全ではありません。ライブラリ libCrun は、コンパイラが依存している多くの「補助」関数が含まれているため置き換えることはできません。
C から派生した 17 個の標準ヘッダー (<stdlib.h>、<stdio.h>、<string.h> など) は、Solaris オペレーティングシステムと基本 Solaris 実行時ライブラリ libc に密接に関連しているため、これらを置き換えることは安全ではありません。これらのヘッダーの C++ 版 (<cstdlib>、<cstdio>、<cstring> など) は基本の C バージョンのヘッダーに密接に関連しているため、これらを置き換えることは安全ではありません。
代替ライブラリをインストールするには、まず、代替ヘッダーの位置と libCstd の代わりに使用するライブラリを決定する必要があります。理解しやすくするために、ここでは、ヘッダーを /opt/mycstd/include にインストールし、ライブラリを /opt/mycstd/lib にインストールすると仮定します。ライブラリの名前は libmyCstd.a であると仮定します。なお、ライブラリの名前を lib で始めると後々便利です。
コンパイルごとに -I オプションを指定して、ヘッダーがインストールされている位置を指示します。さらに、-library=no%Cstd オプションを指定して、コンパイラ独自のバージョンの libCstd ヘッダーが検出されないようにします。たとえば、次のようにします。
example% CC -I/opt/mycstd/include -library=no%Cstd... (compile) |
-library=no%Cstd オプションを指定しているため、コンパイル中、コンパイラ独自のバージョンのヘッダーがインストールされているディレクトリは検索されません。
プログラムまたはライブラリのリンクごとに -library=no%Cstd オプションを指定して、コンパイラ独自の libCstd が検出されないようにします。さらに、-L オプションを指定して、代替ライブラリがインストールされているディレクトリを指示します。さらに、-l オプションを指定して、代替ライブラリを指定します。次に例を示します。
example% CC -library=no%Cstd -L/opt/mycstd/lib -lmyCstd... (link) |
あるいは、-L や -l オプションを使用せずに、ライブラリの絶対パス名を直接指定することもできます。たとえば、次のようにします。
example% CC -library=no%Cstd /opt/mycstd/lib/libmyCstd.a... (link) |
-library=no%Cstd オプションを指定しているため、リンク中、コンパイラ独自のバージョンの libCstd はリンクされません。
C には、<stdio.h>、<string.h>、<stdlib.h> などの 17 個の標準ヘッダーがあります。これらのヘッダーは Solaris オペレーティングシステムに標準で付属しており、/user/include に置かれています。C++ にも同様のヘッダーがありますが、さまざまな宣言の名前が大域の名前空間と std 名前空間の両方に存在するという条件が付加されています。Version 8 より前のリリースの Solaris オペレーティングシステムの C++ コンパイラでは、/usr/include ディレクトリにあるヘッダーはそのまま残して、独自のバージョンのヘッダーを別に用意しています。
また、C++ には、C 標準ヘッダー (<cstdio> 、<cstring>、<cstdlib> など) のそれぞれについても専用のバージョンがあります。C++ 版の C 標準ヘッダーでは、宣言名は std 名前空間にのみ存在します。C++ には、32 個の独自の標準ヘッダー (<string>、<utility>、<iostream> など) も追加されています。
標準ヘッダーの実装で、C++ ソースコード内の名前がインクルードするテキストファイル名として使用されているとしましょう。たとえば、標準ヘッダーの <string> (または <string.h>) が、あるディレクトリにある string (または string.h) というファイルを参照するものとします。この実装には、次の欠点があります。
ヘッダーファイルにファイル名接尾辞 (拡張子) がない場合に、ヘッダーファイルのみを検索すること、またはヘッダーファイルに関する規則を示す makefile を作成することができない。
string というディレクトリまたは実行可能プログラムがあると、そのディレクトリまたはプログラムが標準ヘッダーファイルの代わりに検出される可能性がある。
Solaris 8 オペレーティングシステムより前のリリースの Solaris オペレーティングシステムでは .KEEP_STATE が有効なときのメイクファイルのデフォルトの相互依存関係により、標準ヘッダーが実行可能プログラムに置き換えられる可能性がある (デフォルトの場合、接尾辞がないファイルは構築対象プログラムとみなされる)。
こうした問題を解決するため、コンパイラの include ディレクトリには、ヘッダーと同じ名前を持つファイルと、 一意の接尾辞 .SUNWCCh を持つ、そのファイルへのシンボリックリンクが含まれています。 SUNW はコンパイラに関係するあらゆるパッケージに対する接頭辞、CC は C++ コンパイラの意味、.h はヘッダーファイルの通常の接尾辞です。つまり <string> と指定された場合、コンパイラは <string.SUNWCCh> と書き換え、その名前を検索します。接尾辞付きの名前は、コンパイラ専用の include ディレクトリにだけ存在します。このようにして見つけられたファイルがシンボリックリンクの場合 (通常はそうである)、コンパイラは、エラーメッセージやデバッガの参照でそのリンクを 1 回だけ間接参照し、その参照結果 (この場合は string) をファイル名として使用します。ファイルの依存関係情報を送るときは、接尾辞付きの名前の方が使用されます。
この名前の書き換えは、2 つのバージョンがある 17 個の標準 C ヘッダーと 32 個の標準 C++ ヘッダーのいずれかを、パスを指定せずに山括弧 < > で囲んで指定した場合にだけ行われます。山括弧の代わりに引用符が使用されるか、パスが指定されるか、ほかのヘッダーが指定された場合、名前の書き換えは行われません。
次の表は、よくある書き換え例をまとめています。
表 12–3 ヘッダー検索の例
ソースコード |
コンパイラによる検索 |
注釈 |
---|---|---|
<string> |
string.SUNWCCh |
C++ の文字列テンプレート |
<cstring> |
cstring.SUNWCCh |
C の string.h の C++ 版 |
<string.h> |
string.h.SUNWCCh |
C の string.h |
<fcntl.h> |
fcntl.h |
標準 C および C++ ヘッダー以外 |
"string" |
string |
山括弧ではなく、二重引用符 |
<../string> |
../string |
パス指定がある場合 |
コンパイラが header.SUNWCCh (header はヘッダー名) を見つけられない、コンパイラは、#include 指令で指定された名前で検索し直します。たとえば、#include <string> という指令を指定した場合、コンパイラは string.SUNWCCh という名前のファイルを見つけようとします。この検索が失敗した場合、コンパイラは string という名前のファイルを探します。
「12.7.5 標準ヘッダーの実装」で説明している検索アルゴリズムのため、「12.7.3 代替ライブラリのインストール」で説明している SUNWCCh バージョンの代替 ヘッダーを指定する必要はありません。しかし、これまでに説明したいくつかの問題が発生する可能性もあります。その場合、推奨される解決方法は、接尾辞が付いていないヘッダーごとに、接尾辞 .SUNWCCh を持つファイルに対してシンボリックリンクを作成することです。つまり、ファイルが utility の場合、次のコマンドを実行します。
example% ln -s utility utility.SUNWCCh |
utility.SUNWCCh というファイルを探すとき、コンパイラは 1 回目の検索でこのファイルを見つけます。そのため、utility という名前のほかのファイルやディレクトリを誤って検出してしまうことはありません。
標準 C ヘッダーの置き換えはサポートされていません。それでもなお、独自のバージョンの標準ヘッダーを使用したい場合、推奨される手順は次のとおりです。
すべての代替ヘッダーを 1 つのディレクトリに置きます。
そのディレクトリ内にある代替ヘッダーごとに header.SUNWCCh (header はヘッダー名) へのシンボリックリンクを作成します。
コンパイラを呼び出すごとに -I 指令を指定して、代替ヘッダーが置かれているディレクトリが検索されるようにします。
たとえば、<stdio.h> と <cstdio> の代替ヘッダーがあるとします。stdio.h と cstdio をディレクトリ /myproject/myhdr に置きます。このディレクトリ内で、次のコマンドを実行します。
example% ln -s stdio.h stdio.h.SUNWCCh example% ln -s cstdio cstdio.SUNWCCh |
コンパイルのたびに、オプション -I/myproject/mydir を使用します。
C ヘッダーを置き換える場合は、対になっているもう一方のヘッダーを置き換える必要があります。たとえば、<time.h> を置き換えるときは、<ctime> も置き換える必要があります。
代替ヘッダーは、置き換える前のヘッダーと同じ効果を持っている必要があります。これは、さまざまな実行時ライブラリ (libCrun、libC、libCstd、libc、および librwtool) が標準ヘッダーの定義を使用して構築されているためです。同じ効果を持っていない場合、作成したプログラムはほとんどの場合、正しく動作しません。
デフォルトモード (標準モード) のコンパイルでは、コンパイラは C++ 標準で指定されている完全なライブラリにアクセスします。このライブラリには、非公式に「標準テンプレートライブラリ」 (STL) と呼ばれているものに加えて、次の要素が含まれています。
文字列クラス
数値クラス
標準のストリーム入出力クラス
基本的なメモリー割り当て
例外クラス
実行時の型識別 (RTTI)
STL は公式なものではありませんが、一般的にはコンテナ、反復子、アルゴリズムから構成されます。標準ライブラリのヘッダーのうち、次のものを STL の構成要素と見なすことができます。
<algorithm>
<deque>
<iterator>
<list>
<map>
<memory>
<queue>
<set>
<stack>
<utility>
<vector>
C++ 標準ライブラリ (libCstd) は、RogueWaveTM 標準 C++ ライブラリ、Version 2 に基づいています。このライブラリは、コンパイラのデフォルトモード (-compat=5) でのみ使用でき、-compat[=4] オプションと組み合わせた使用はサポートされていません。
また、C++ コンパイラで、STLport の標準ライブラリの Version 4.5.3 がサポートされました。libCstd がデフォルトのライブラリですが、代わりに STLport の製品を使用できるようになりました。詳細は、「13.3 STLport」を参照してください。
コンパイラに付属している C++ 標準ライブラリの代わりに、独自の C++ 標準ライブラリを使用できます。その場合は、-library=no%Cstd オプションを使用します。ただし、コンパイラに添付された標準ライブラリを置き換えることは危険で、必ずしもよい結果につながるわけではありません。詳細は、「12.7 C++ 標準ライブラリの置き換え」を参照してください。
標準ライブラリの詳細については、『標準 C++ ライブラリユーザーズガイド』と『Standard C++ Class Library Reference』を参照してください。
標準ライブラリのヘッダーとその概要は表 13–1 に一覧表示します。
表 13–1 C++ 標準ライブラリのヘッダーファイル
ヘッダーファイル |
内容の説明 |
---|---|
<algorithm> |
コンテナ操作のための標準アルゴリズム |
<bitset> |
固定長のビットシーケンス |
<complex> |
複素数を表す数値型 |
<deque> |
先頭と末尾の両方で挿入と削除が可能なシーケンス |
<exception> |
事前定義済み例外クラス |
<fstream> |
ファイルとのストリーム入出力 |
<functional> |
関数オブジェクト |
<iomanip> |
iostream のマニピュレータ |
<ios> |
iostream の基底クラス |
<iosfwd> |
iostream クラスの先行宣言 |
<iostream> |
基本的なストリーム入出力機能 |
<istream> |
入力ストリーム |
<iterator> |
シーケンスの内容にくまなくアクセスするためのクラス |
<limits> |
数値型の属性 |
<list> |
順序付きシーケンス |
<locale> |
国際化のサポート |
<map> |
キーと値を対にして使用する連想コンテナ |
<memory> |
特殊なメモリーアロケータ |
<new> |
基本的なメモリー割り当てと解放 |
<numeric> |
汎用の数値演算 |
<ostream> |
出力ストリーム |
<queue> |
先頭への挿入と末尾からの削除が可能なシーケンス |
<set> |
一意キーを使用する連想コンテナ |
<sstream> |
メモリー上の文字列との入出力ストリーム |
<stack> |
先頭への挿入と先頭からの削除が可能なシーケンス |
<stdexcept> |
追加標準例外クラス |
<streambuf> |
iostream 用のバッファークラス |
<string> |
文字シーケンス |
<typeinfo> |
実行時の型識別 |
<utility> |
比較演算子 |
<valarray> |
数値プログラミング用の値配列 |
<vector> |
ランダムアクセスが可能なシーケンス |
標準ライブラリの個々の構成要素のマニュアルページを表 13–2 に一覧表示します。
表 13–2 C++ 標準ライブラリのマニュアルページ
マニュアルページ |
概要 |
---|---|
Algorithms |
コンテナとシーケンスに各種処理を行うための汎用アルゴリズム |
Associative_Containers |
特定の順序で並んだコンテナ |
Bidirectional_Iterators |
読み書きの両方が可能で、順方向、逆方向にコンテナをたどることができる反復子 |
Containers |
標準テンプレートライブラリ (STL) コレクション |
Forward_Iterators |
読み書きの両方が可能な順方向反復子 |
Function_Objects |
operator() が定義済みのオブジェクト |
Heap_Operations |
make_heap、pop_heap、push_heap、sort_heap を参照 |
Input_Iterators |
読み取り専用の順方向反復子 |
Insert_Iterators |
反復子がコンテナ内の要素を上書きせずにコンテナに挿入することを可能にする、反復子アダプタ |
Iterators |
コレクションをたどったり、変更したりするためのポインタ汎用化機能 |
Negators |
述語関数オブジェクトの意味を逆にするための関数アダプタと関数オブジェクト |
Operators |
C++ 標準テンプレートライブラリ出力用の演算子 |
Output_Iterators |
書き込み専用の順方向反復子 |
Predicates |
ブール値 (真偽) または整数値を返す関数または関数オブジェクト |
Random_Access_Iterators |
コンテナの読み取りと書き込みをして、コンテナにランダムアクセスすることを可能にする反復子 |
Sequences |
一群のシーケンスをまとめたコンテナ |
Stream_Iterators |
汎用アルゴリズムをストリームに直接に使用することを可能にする、ostream と istream 用の反復子機能を含む |
__distance_type |
反復子が使用する距離のタイプを決定する (廃止予定) |
__iterator_category |
反復子が属するカテゴリを決定する (廃止予定) |
__reverse_bi_iterator |
コレクションを逆方向にたどる反復子 |
accumulate |
1 つの範囲内のすべての要素の累積値を求める |
adjacent_difference |
1 つの範囲内の隣り合う 2 つの要素の差のシーケンスを出力する |
adjacent_find |
シーケンスから、等しい値を持つ最初の 2 つの要素を検出する |
advance |
特定の距離で、順方向または逆方向 (使用可能な場合) に反復子を移動する |
allocator |
標準ライブラリコンテナ内の記憶管理用のデフォルトの割り当てオブジェクト |
auto_ptr |
単純でスマートなポインタクラス |
back_insert_iterator |
コレクションの末尾への項目の挿入に使用する挿入反復子 |
back_inserter |
コレクションの末尾への項目の挿入に使用する挿入反復子 |
basic_filebuf |
入力または出力シーケンスをファイルに関連付ける |
basic_fstream |
1 つのファイル記述子に関連付けられた、複数の指定ファイルまたはその他デバイスに対する読み書きをサポートする |
basic_ifstream |
1 つのファイル記述子に関連付けられた、複数の指定ファイルまたはその他デバイスからの読み取りをサポートする |
basic_ios |
すべてのストリームが共通に必要とする関数を取り込む基底クラス |
basic_iostream |
ストリームバッファーが制御する文字シーケンスの書式設定と解釈をサポートする |
basic_istream |
ストリームバッファーが制御する文字シーケンスからの入力の読み取りと解釈をサポートする |
basic_istringstream |
メモリー上の配列から basic_string<charT,traits,Allocator> クラスのオブジェクトの読み取りをサポートする |
basic_ofstream |
1 つのファイル記述子に関連付けられた、複数の指定ファイルまたはその他デバイスへの書き込みをサポートする |
basic_ostream |
ストリームバッファーが制御するシーケンスに対する出力の書式設定と書き込みをサポートする |
basic_ostringstream |
basic_string<charT,traits,Allocator> クラスのオブジェクトの書き込みをサポートする |
basic_streambuf |
各種のストリームバッファーを派生させて、文字シーケンスを制御しやすいようにする抽象基底クラス |
basic_string |
文字に似た要素シーケンスを処理するためのテンプレート化されたクラス |
basic_stringbuf |
入力または出力シーケンスを任意の文字シーケンスに関連付ける |
basic_stringstream |
メモリー上の配列への basic_string<charT,traits,Allocator> クラスのオブジェクトの書き込みと読み取りをサポートする |
binary_function |
2 項関数オブジェクトを作成するための基底クラス |
binary_negate |
2 項判定子の結果の補数を返す関数オブジェクト |
binary_search |
コンテナ上の値について 2 等分検索を行う |
bind1st |
関数オブジェクトに値を結合するためのテンプレート化されたユーティリティー |
bind2nd |
関数オブジェクトに値を結合するためのテンプレート化されたユーティリティー |
binder1st |
関数オブジェクトに値を結合するためのテンプレート化されたユーティリティー |
binder2nd |
関数オブジェクトに値を結合するためのテンプレート化されたユーティリティー |
bitset |
固定長のビットシーケンスを格納、操作するためのテンプレートクラスと関数 |
cerr |
<cstdio> で宣言されたオブジェクトの stderr に関連付けられたバッファリングしていないストリームバッファーに対する出力を制御する |
char_traits |
basic_string コンテナと iostream クラス用の型と演算を持つ特性 (traits) クラス |
cin |
<cstdio> で宣言されたオブジェクトの stdin に関連付けられたストリームバッファーからの入力を制御する |
clog |
<cstdio> で宣言されたオブジェクトの stderr に関連付けられたストリームバッファーに対する出力を制御する |
codecvt |
コード変換ファセット |
codecvt_byname |
指定ロケールに基づいたコードセット変換分類機能を含むファセット |
collate |
文字列照合、比較、ハッシュファセット |
collate_byname |
文字列照合、比較、ハッシュファセット |
compare |
真または偽を返す 2 項関数または関数オブジェクト |
complex |
C++ 複素数ライブラリ |
copy |
ある範囲の要素をコピーする |
copy_backward |
ある範囲の要素をコピーする |
count |
指定条件を満たすコンテナ内の要素の個数をカウントする |
count_if |
指定条件を満たすコンテナ内の要素の個数をカウントする |
cout |
<cstdio> で宣言されたオブジェクトの stderr に関連付けられたストリームバッファーに対する出力を制御する |
ctype |
文字分類機能を取り込むファセット |
ctype_byname |
指定ロケールに基づいた文字分類機能を含むファセット |
deque |
ランダムアクセス反復子と、先頭および末尾の両方での効率的な挿入と削除をサポートするシーケンス |
distance |
2 つの反復子間の距離を求める |
divides |
1 つ目の引数を 2 つ目の引数で除算した結果を返す |
equal |
2 つのある範囲が等しいかどうか比較する |
equal_range |
並べ替えの順序を崩さずに値を挿入できる最大の二次範囲をコレクションから検出する |
equal_to |
1 つ目と 2 つ目の引数が等しい場合に真を返す 2 項関数オブジェクト |
exception |
倫理エラーと実行時エラーをサポートするクラス |
facets |
複数種類のロケール機能をカプセル化するために使用するクラス群 |
filebuf |
入力または出力シーケンスをファイルに関連付ける |
fill |
指定された値である範囲を初期化する |
fill_n |
指定された値である範囲を初期化する |
find |
シーケンスから値に一致するものを検出する |
find_end |
シーケンスからサブシーケンスに最後に一致するものを検出する |
find_first_of |
シーケンスから、別のシーケンスの任意の値に一致するものを検出する |
find_if |
シーケンスから指定された判定子を満たす値に一致するものを検出する |
for_each |
ある範囲のすべての要素に関数を適用する |
fpos |
iostream クラスの位置情報を保持する |
front_insert_iterator |
コレクションの先頭に項目を挿入するための挿入反復子 |
front_inserter |
コレクションの先頭に項目を挿入するための挿入反復子 |
fstream |
1 つのファイル記述子に関連付けられた、複数の指定ファイルまたはその他デバイスに対する読み書きをサポートする |
generate |
値生成クラスによって生成された値でコンテナを初期化する |
generate_n |
値生成クラスによって生成された値でコンテナを初期化する |
get_temporary_buffer |
メモリーを処理するためのポインタベースのプリミティブ |
greater |
1 つ目の引数が 2 つ目の引数より大きい場合に真を返す 2 項関数オブジェクト |
greater_equal |
1 つ目の引数が 2 つ目の引数より大きいか等しい場合に真を返す 2 項関数オブジェクト |
gslice |
配列から汎用化されたスライスを表現するために使用される数値配列クラス |
gslice_array |
valarray から BLAS に似たスライスを表現するために使用される数値配列クラス |
has_facet |
ロケールに指定ファセットがあるかどうかを判定するための関数テンプレート |
ifstream |
1 つのファイル記述子に関連付けられた、複数の指定ファイルまたはその他デバイスからの読み取りをサポートする |
includes |
ソートされたシーケンスに対する基本演算セット |
indirect_array |
valarray から選択された要素の表現に使用される数値配列クラス |
inner_product |
2 つの範囲 A および B の内積 (A × B) を求める |
inplace_merge |
ソートされた 2 つのシーケンスを 1 つにマージする |
insert_iterator |
コレクションを上書きせずにコレクションに項目を挿入するときに使用する挿入反復子 |
inserter |
コレクションを上書きせずにコレクションに項目を挿入するときに使用する挿入反復子 |
ios |
すべてのストリームが共通に必要とする関数を取り込む基底クラス |
ios_base |
メンバーの型を定義して、そのメンバーから継承するクラスのデータを保持する |
iosfwd |
入出力ライブラリテンプレートクラスを宣言し、そのクラスを wide および tiny 型文字専用にする |
isalnum |
文字が英字または数字のどちらであるかを判定する |
isalpha |
文字が英字であるかどうかを判定する |
iscntrl |
文字が制御文字であるかどうかを判定する |
isdigit |
文字が 10 進数であるかどうかを判定する |
isgraph |
文字が図形文字であるかどうかを判定する |
islower |
文字が英小文字であるかどうかを判定する |
isprint |
文字が印刷可能かどうかを判定する |
ispunct |
文字が区切り文字であるかどうかを判定する |
isspace |
文字が空白文字であるかどうかを判定する |
istream |
ストリームバッファーが制御する文字シーケンスからの入力の読み取りと解釈をサポートする |
istream_iterator |
istream に対する反復子機能を持つストリーム反復子 |
istreambuf_iterator |
作成元のストリームバッファーから連続する文字を読み取る |
istringstream |
メモリー上の配列からの basic_string<charT,traits,Alocator> クラスのオブジェクトの読み取りをサポートする |
istrstream |
メモリー上の配列から文字を読み取る |
isupper |
文字が英大文字であるかどうかを判定する |
isxdigit |
文字が 16 進数であるかどうかを判定する |
iter_swap |
2 つの位置の値を交換する |
iterator |
基底反復子クラス |
iterator_traits |
反復子に関する基本的な情報を返す |
less |
1 つ目の引数が 2 つ目の引数より小さい場合に真を返す 2 項関数オブジェクト |
less_equal |
1 つ目の引数が 2 つ目の引数より小さいか、等しい場合に真を返す 2 項関数オブジェクト |
lexicographical_compare |
2 つの範囲を辞書式に比較する |
limits |
numeric_limits セクションを参照 |
list |
双方向反復子をサポートするシーケンス |
locale |
多相性を持つ複数のファセットからなるローカリゼーションクラス |
logical_and |
1 つ目の 2 つ目の引数が等しい場合に真を返す場合に 2 項関数オブジェクト |
logical_not |
引数が偽の場合に真を返す単項関数オブジェクト |
logical_or |
引数のいずれかが真の場合に真を返す 2 項関数オブジェクト |
lower_bound |
ソートされたコンテナ内の最初に有効な要素位置を求める |
make_heap |
ヒープを作成する |
map |
一意のキーを使用してキー以外の値にアクセスする連想コンテナ |
mask_array |
valarray の選別ビューを提供する数値配列クラス |
max |
2 つの値の大きい方の値を検出して返す |
max_element |
1 つの範囲内の最大値を検出する |
mem_fun |
大域関数の代わりとしてポインタをメンバー関数に適合させる関数オブジェクト |
mem_fun1 |
大域関数の代わりとしてポインタをメンバー関数に適合させる関数オブジェクト |
mem_fun_ref |
大域関数の代わりとしてポインタをメンバー関数に適合させる関数オブジェクト |
mem_fun_ref1 |
大域関数の代わりとしてポインタをメンバー関数に適合させる関数オブジェクト |
merge |
ソートされた 2 つのシーケンスをマージして、3 つ目のシーケンスを作成する |
messages |
メッセージ伝達ファセット |
messages_byname |
メッセージ伝達ファセット |
min |
2 つの値の小さい方の値を検出して返す |
min_element |
1 つの範囲内の最小値を検出する |
minus |
1 つ目の引数から 2 つ目の引数を減算した結果を返す |
mismatch |
2 つのシーケンスの要素を比較して、互いに値が一致しない最初の 2 つの要素を返す |
modulus |
1 つ目の引数を 2 つ目の引数で除算することによって得られた余りを返す |
money_get |
入力に対する通貨書式設定ファセット |
money_put |
出力に対する通貨書式設定ファセット |
moneypunct |
通貨句読文字ファセット |
moneypunct_byname |
通貨句読文字ファセット |
multimap |
キーを使用してコンテナキーでない値にアクセスするための連想コンテナ |
multiplies |
1 つ目と 2 つ目の引数を乗算した結果を返す 2 項関数オブジェクト |
multiset |
格納済みのキー値に高速アクセスするための連想コンテナ |
negate |
引数の否定値を返す単項関数オブジェクト |
next_permutation |
並べ替え関数に基づいてシーケンスの内容を連続的に入れ替えたものを生成する |
not1 |
単項述語関数オブジェクトの意味を逆にするための関数アダプタ |
not2 |
単項述語関数オブジェクトの意味を逆にするための関数アダプタ |
not_equal_to |
1 つ目の引数が 2 つ目の引数と等しくない場合に真を返す 2 項関数オブジェクト |
nth_element |
コレクションを再編して、ソートで n 番目の要素よりあとになった全要素をその要素より前に、n 番目の要素より前の全要素をその要素より後ろにくるようにする |
num_get |
入力に対する書式設定ファセット |
num_put |
出力に対する書式設定ファセット |
numeric_limits |
スカラー型に関する情報を表すためのクラス |
numpunct |
数値句読文字ファセット |
numpunct_byname |
数値句読文字ファセット |
ofstream |
1 つのファイル記述子に関連付けられた、複数の指定ファイルまたはその他デバイスへの書き込みをサポートする |
ostream |
ストリームバッファーが制御するシーケンスに対する出力の書式設定と書き込みをサポートする |
ostream_iterator |
ostream と istream に反復子を使用可能にするストリーム反復子 |
ostreambuf_iterator |
作成元のストリームバッファーに連続する文字を書き込む |
ostringstream |
basic_string<charT,traits,Allocator> クラスのオブジェクトの書き込みをサポートする |
ostrstream |
メモリー上の配列に書き込みを行う |
pair |
異種の値の組み合わせ用テンプレート |
partial_sort |
エンティティーのコレクションをソートするためのテンプレート化されたアルゴリズム |
partial_sort_copy |
エンティティーのコレクションをソートするためのテンプレート化されたアルゴリズム |
partial_sum |
ある範囲の値の連続した部分小計を求める |
partition |
指定述語を満たす全エンティティーを、満たさない全エンティティーの前に書き込む |
permutation |
並べ替え関数に基づいてシーケンスの内容を連続的に入れ替えたものを生成する |
plus |
1 つ目と 2 つ目の引数を加算した結果を返す 2 項関数オブジェクト |
pointer_to_binary_function |
binary_function の代わりとしてポインタを 2 項関数に適用する関数オブジェクト |
pointer_to_unary_function |
unary_function の代わりとしてポインタを関数に適用する関数オブジェクトクラス |
pop_heap |
ヒープの外に最大要素を移動する |
prev_permutation |
並べ替え関数に基づいてシーケンスの内容を連続的に入れ替えたものを生成する |
priority_queue |
優先順位付きの待ち行列のように振る舞うコンテナアダプタ |
ptr_fun |
関数の代わりとしてポインタを関数に適用するときに多重定義される関数 |
push_heap |
ヒープに新しい要素を書き込む |
queue |
先入れ先出しの待ち行列のように振る舞うコンテナアダプタ |
random_shuffle |
コレクションの要素を無作為にシャッフルする |
raw_storage_iterator |
反復子ベースのアルゴリズムが初期化されていないメモリーに結果を書き込めるようにする |
remove |
目的の要素をコンテナの先頭に移動し、目的の要素シーケンスの終了位置を表す反復子を返す |
remove_copy |
目的の要素をコンテナの先頭に移動し、目的の要素シーケンスの終了位置を表す反復子を返す |
remove_copy_if |
目的の要素をコンテナの先頭に移動し、目的の要素シーケンスの終了位置を表す反復子を返す |
remove_if |
目的の要素をコンテナの先頭に移動し、目的の要素シーケンスの終了位置を表す反復子を返す |
replace |
コレクション内の要素の値を置換する |
replace_copy |
コレクション内の要素の値を置換して、置換後のシーケンスを結果に移動する |
replace_copy_if |
コレクション内の要素の値を置換して、置換後のシーケンスを結果に移動する |
replace_if |
コレクション内の要素の値を置換する |
return_temporary_buffer |
メモリーを処理するためのポインタベースのプリミティブ |
reverse |
コレクション内の要素を逆順にする |
reverse_copy |
コレクション内の要素を逆順にしながら、その結果を新しいコレクションにコピーする |
reverse_iterator |
コレクションを逆方向にたどる反復子 |
rotate |
先頭から中央直前の要素までのセグメントと中央から末尾までの要素のセグメントを交換する |
rotate_copy |
先頭から中央直前の要素までのセグメントと中央から末尾までの要素のセグメントを交換する |
search |
値シーケンスから、要素単位で指定範囲の値に等しいサブシーケンスを検出する |
search_n |
値シーケンスから、要素単位で指定範囲の値に等しいサブシーケンスを検出する |
set |
一意のキーを扱う連想コンテナ |
set_difference |
ソートされた差を作成する基本的な集合演算 |
set_intersection |
ソートされた積集合を作成する基本的な集合演算 |
set_symmetric_difference |
ソートされた対称差を作成する基本的な集合演算 |
set_union |
ソートされた和集合を作成する基本的な集合演算 |
slice |
配列の BLAS に似たスライスを表す数値配列クラス |
slice_array |
valarray の BLAS に似たスライスを表す数値配列クラス |
smanip |
パラメータ化されたマニピュレータを実装するときに使用する補助クラス |
smanip_fill |
パラメータ化されたマニピュレータを実装するときに使用する補助クラス |
sort |
エンティティーのコレクションをソートするためのテンプレート化されたアルゴリズム |
sort_heap |
ヒープをソートされたコレクションに変換する |
stable_partition |
各グループ内の要素の相対的な順序を保持しながら、指定判定子を満たす全エンティティーを満たさない全エンティティーの前に書き込む |
stable_sort |
エンティティーのコレクションをソートするためのテンプレート化されたアルゴリズム |
stack |
先入れ先出しのスタックのように振る舞うコンテナアダプタ |
streambuf |
各種のストリームバッファーを派生させて、文字シーケンスを制御しやすいようにする抽象基底クラス |
string |
basic_string<char、char_traits<char>、allocator<char>> 用の型定義 |
stringbuf |
入力または出力シーケンスを任意の文字シーケンスに関連付ける |
stringstream |
メモリー上の配列上の basic_string<charT,traits,Alocator> クラスのオブジェクトの書き込みおよび読み取りをサポートする |
strstream |
メモリー上の配列に対する読み取りと書き込みを行う |
strstreambuf |
入力または出力シーケンスを、要素が任意の値を格納する超小型の文字配列に関連付ける |
swap |
値を交換する |
swap_ranges |
ある位置の値の範囲を別の位置の値と交換する |
time_get |
入力に対する時刻書式設定ファセット |
time_get_byname |
指定ロケールに基づいた、入力に対する時刻書式設定ファセット |
time_put |
入力に対する時刻書式設定ファセット |
time_put_byname |
指定ロケールに基づいた、入力に対する時刻書式設定ファセット |
tolower |
文字を小文字に変換する |
toupper |
文字を大文字に変換する |
transform |
コレクション内の値の範囲に演算を適用し、結果を格納する |
unary_function |
単項関数オブジェクトを作成するための基底クラス |
unary_negate |
単項述語の結果の補数を返す関数オブジェクト |
uninitialized_copy |
構造構文を使用してある範囲の値を別の位置にコピーするアルゴリズム |
uninitialized_fill |
コレクション内の値の設定に構造構文アルゴリズムを使用するアルゴリズム |
uninitialized_fill_n |
コレクション内の値の設定に構造構文アルゴリズムを使用するアルゴリズム |
unique |
1 つの範囲の値から連続する重複値を削除し、得られた一意の値を結果に書き込む |
unique_copy |
1 つの範囲の値から連続する重複値を削除し、得られた一意の値を結果に書き込む |
upper_bound |
ソートされたコンテナ内の最後に有効な値位置を求める |
use_facet |
ファセットの取得に使用するテンプレート関数 |
valarray |
数値演算用に最適化された配列クラス |
vector |
ランダムアクセス反復子をサポートするシーケンス |
wcerr |
<cstdio> で宣言されたオブジェクトの stderr に関連付けられたバッファリングしていないストリームバッファーに対する出力を制御する |
wcin |
<cstdio> で宣言されたオブジェクトの stdin に関連付けられたストリームバッファーからの入力を制御する |
wclog |
<cstdio> で宣言されたオブジェクトの stderr に関連付けられたストリームバッファーに対する出力を制御する |
wcout |
<cstdio> で宣言されたオブジェクトの stderr に関連付けられたストリームバッファーに対する出力を制御する |
wfilebuf |
入力または出力シーケンスをファイルに関連付ける |
wfstream |
1 つのファイル記述子に関連付けられた、複数の指定ファイルまたはその他デバイスに対する読み書きをサポートする |
wifstream |
1 つのファイル記述子に関連付けられた、複数の指定ファイルまたはその他デバイスからの読み取りをサポートする |
wios |
すべてのストリームが共通に必要とする関数を取り込む基底クラス |
wistream |
ストリームバッファーが制御する文字シーケンスからの入力の読み取りと解釈をサポートする |
wistringstream |
メモリー上の配列からの basic_string<charT,traits,Allocator&; クラスのオブジェクトの読み取りをサポートする |
wofstream |
1 つのファイル記述子に関連付けられた、複数の指定ファイルまたはその他デバイスへの書き込みをサポートする |
wostream |
ストリームバッファーが制御するシーケンスに対する出力の書式設定と書き込みをサポートする |
wostringstream |
basic_string<charT,traits,Allocator> クラスのオブジェクトの書き込みをサポートする |
wstreambuf |
各種のストリームバッファーを派生させて、文字シーケンスを制御しやすいようにする抽象基底クラス |
wstring |
basic_string<wchar_t, char_traits<wchar_t>、allocator<wchar_t>>用の型定義 |
wstringbuf |
入力または出力シーケンスを任意の文字シーケンスに関連付ける |
libCstd の代替ライブラリを使用する場合は、標準ライブラリの STLport 実装を使用します。 libCstd をオフにして、STLport ライブラリで代用するには、次のコンパイラオプションを使用します。
-library=stlport4
詳細は、「A.2.50 -library=l[ ,l...]」を参照してください。
このリリースでは、libstlport.a という静的アーカイブおよび libstlport.so という動的ライブラリの両方が含まれています。
STLport 実装を使用するかどうかは、次のことを考慮して判断してください。
STLport は、オープンソースの製品で、リリース間での互換性は保証されません。つまり、将来のバージョンの STLport でコンパイルすると、STLport 4.5.3 でコンパイルしたアプリケーションで問題が発生する可能性があります。また、STLport 4.5.3 でコンパイルしたバイナリは、将来のバージョンの STLport でコンパイルしたバイナリとリンクできない可能性があります。
stlport4、Cstd、および iostream のライブラリは、固有の入出力ストリームを実装しています。これらのライブラリの 2 個以上を-library オプションを使って指定した場合、プログラム動作が予期しないものになる恐れがあります。
コンパイラの将来のリリースには、STLport4 が含まれない可能性があります。STLport の新しいバージョンだけが含まれる可能性があります。コンパイラオプションの -library=stlport4 は、将来のリリースでは使用できず、STLport のそれ以降のバージョンを示すオプションに変更される可能性があります。
STLport では、Tools.h++ はサポートされません。
STLport は、デフォルトの libCstd とはバイナリ互換ではありません。STLport の標準ライブラリの実装を使用する場合は、-library=stlport4 オプションを指定してすべてのファイルのコンパイルおよびリンクを実行する必要があります。このことは、たとえば STLport 実装と C++ 区間演算ライブラリ libCsunimath を同時に使用できないことを意味します。その理由は、libCsunimath のコンパイルに使用されたのが、STLport ではなくデフォルトライブラリヘッダーであるためです。
STLport 実装を使用する場合は、コードから暗黙に参照されるヘッダーファイルをインクルードしてください。標準のヘッダーは、実装の一部として相互にインクルードできます (必須ではありません)。
-compat=4 によってコンパイルする場合には、STLport 実装を使用できません。
エンドユーザーオブジェクトコードライセンスの条件に基づいて、作成した実行可能ファイルまたはライブラリとともに再配布可能なライブラリおよびオブジェクトファイルの一覧は、実行時ライブラリの README を参照してください。この README の C++ セクションに、このリリースのコンパイラがサポートしている STLport .so のバージョンが記載されています。この Readme は製品ドキュメントの一部として、Sun Studio SDN ポータルの http://developers.sun.com/sunstudio/documentation/ から入手できます。
次の例は、ライブラリの実装について移植性のない想定が行われているため、STLport を使用してコンパイルできません。特に、<vector> または <iostream> が <iterator> を自動的にインクルードすることを想定していますが、これは正しい想定ではありません。
#include <vector> #include <iostream> using namespace std; int main () { vector <int> v1 (10); vector <int> v3 (v1.size()); for (int i = 0; i < v1.size (); i++) {v1[i] = i; v3[i] = i;} vector <int> v2(v1.size ()); copy_backward (v1.begin (), v1.end (), v2.end ()); ostream_iterator<int> iter (cout, " "); copy (v2.begin (), v2.end (), iter); cout << endl; return 0; } |
問題を解決するには、ソースで <iterator> をインクルードします。
C++ も C と同様に組み込み型の入出力文はありません。その代わりに、出力機能はライブラリで提供されています。C++ コンパイラでは iostream クラスに対して、従来型の実装と ISO 標準の実装を両方とも提供しています。
標準モード (デフォルトのモード) では、従来型の io stream クラスは libiostream に含まれています。従来型の libiostream クラスを使用したソースコードを標準モードでコンパイルするときは、 iostream を使用します。従来型の iostream の機能を標準モードで使用するには、iostream.h ヘッダーファイルをインクルードし、-library=iostream オプションを使用してコンパイルします。
標準の iostream クラスは標準モードだけで使用でき、C++ 標準ライブラリ libCstd に含まれています。
この章では、従来型の iostream ライブラリの概要と使用例を説明します。この章では、iostream ライブラリを完全に説明しているわけではありません。詳細は、iostream ライブラリのマニュアルページを参照してください。従来型の iostream のマニュアルページを表示するには、次のように入力します (name にはマニュアルページのトピック名を入力)。man -s 3CC4 name
定義済みの iostream には、次のものがあります。
定義済み iostream は、cerr を除いて完全にバッファ利用します。「14.3.1 iostream を使用した出力」と 「14.3.2 iostream を使用した入力」を参照してください。
iostream ライブラリを使用すると、プログラムで必要な数の入出力ストリームを使用できます。それぞれのストリームは、次のどれかを入力先または出力先とします。
標準入力
標準出力
標準エラー
ファイル
文字型配列
ストリームは、入力のみまたは出力のみと制限して使用することも、入出力両方に使用することもできます。iostream ライブラリでは、次の 2 つの処理階層を使用してこのようなストリームを実現しています。
下層では、単なる文字ストリームであるシーケンスを実現します。シーケンスは、streambuf クラスか、その派生クラスで実現されています。
上層では、シーケンスに対してフォーマット操作を行います。フォーマット操作は istream と ostream の 2 つのクラスで実現されます。これらのクラスはメンバーに streambuf クラスから派生したオブジェクトを持っています。このほかに、入出力両方が実行されるストリームに対しては iostream クラスがあります。
標準入力、標準出力、標準エラーは、istream または ostream から派生した特殊なクラスオブジェクトで処理されます。
ifstream、ofstream、fstream の 3 つのクラスはそれぞれ istream、ostream、iostream から派生しており、ファイルへの入出力を処理します。
istrstream、ostrstream、strstream の 3 つのクラスはそれぞれ istream、ostream、および iostream から派生しており、文字型配列への入出力を処理します。
入力ストリームまたは出力ストリームをオープンする場合は、どれかの型のオブジェクトを生成し、そのストリームのメンバー streambuf をデバイスまたはファイルに関連付けます。通常、関連付けはストリームコンストラクタで行うので 、ユーザーが直接 streambuf を操作することはありません。標準入力、標準出力、エラー出力に対しては、iostream ライブラリであらかじめストリームオブジェクトを定義してあるので、これらのストリームについてはユーザーが独自にオブジェクトを生成する必要はありません。
ストリームへのデータの挿入 (出力)、ストリームからのデータの抽出 (入力)、挿入または抽出したデータのフォーマット制御には、演算子または iostream のメンバー関数を使用します。
新たなデータ型 (ユーザー定義のクラス) を挿入したり抽出したりするときは一般に、挿入演算子と抽出演算子の多重定義をユーザーが行います。
従来型の iostream ライブラリからルーチンを使用するには、必要なライブラリ部分のヘッダーファイルをインクルードする必要があります。 次の表で各ヘッダーファイルについて説明します。
表 14–1 iostream ルーチンのヘッダーファイル
これらのヘッダーファイルすべてをプログラムにインクルードする必要はありません。自分のプログラムで必要な宣言の入ったものだけをインクルードします。互換モード (-compat[=4]) では、従来型の iostream ライブラリは libC の一部であり、CC ドライバによって自動的にリンクされます。標準モード (デフォルトのモード) では、従来型の libiostream ライブラリは iostream に含まれています。
iostream を使用した出力は、通常、左シフト演算子 (<<) を多重定義したもの (iostream の文脈では挿入演算子といいます) を使用します。ある値を標準出力に出力するには、その値を定義済みの出力ストリーム cout に挿入します。たとえば someValue を出力するには、次の文を標準出力に挿入します。
cout << someValue; |
挿入演算子は、すべての組み込み型について多重定義されており、someValue の値は適当な出力形式に変換されます。たとえば someValue が float 型の場合、<< 演算子はその値を数字と小数点の組み合わせに変換します。float 型の値を出力ストリームに挿入するときは、<< を float 型挿入子といいます。一般に X 型の値を出力ストリームに挿入するときは、<< を X 型挿入子といいます。出力形式とその制御方法については、ios(3CC4) のマニュアルページを参照してください。
iostream ライブラリは、ユーザー定義の型をサポートしていません。独自の方法で出力しようとする型を定義する場合は、それらを正しく処理する挿入子を定義する (つまり、<<operator を多重定義する) 必要があります。
<< 演算子は反復使用できます。2 つの値を cout に挿入するには、次の例のような文を使用できます。
cout << someValue << anotherValue; |
前述の例では、2 つの値の間に空白が入りません。空白を入れる場合は、次のようにします。
cout << someValue << " " << anotherValue; |
<< 演算子は、組み込みの左シフト演算子と同じ優先順位を持ちます。ほかの演算子と同様に、括弧を使用して実行順序を指定できます。 実行順序をはっきりさせるためにも、括弧を使用するとよい場合がよくあります。次の 4 つの文のうち、最初の 2 つは同じ結果になりますが、あとの 2 つは異なります。
cout << a+b; // + has higher precedence than << cout << (a+b); cout << (a&y); // << has precedence higher than & cout << a&y; // probably an error: (cout << a) & y |
次のコーディング例では string クラスを定義しています。
#include <stdlib.h> #include <iostream.h> class string { private: char* data; size_t size; public: // (functions not relevant here) friend ostream& operator<<(ostream&, const string&); friend istream& operator>>(istream&, string&); }; |
この例では、string クラスのデータ部が private であるため、挿入演算子と抽出演算子をフレンド定義しておく必要があります。
ostream& operator<< (ostream& ostr, const string& output) { return ostr << output.data;} |
前述の定義は、string クラスに対して多重定義された演算子関数 operator<< の定義です。
cout << string1 << string2; |
operator<< は、最初の引数として ostream& (ostream への参照) を受け取り、同じ ostream を返します。このため、次のように 1 つの文で挿入演算子を続けて使用できます。
operator<< を多重定義するときは、iostream ライブラリからエラーが通知されることになるため、特にエラー検査を行う必要はありません。
エラーが起こると、エラーの起こった iostream は エラー状態になります。その iostream の状態の各ビットが、エラーの大きな分類に従ってセットされます。iostream で定義された挿入子がストリームにデータを挿入しようとしても、そのストリームがエラー状態の場合はデータが挿入されず、iostream の状態も変わりません。
一般的なエラー処理方法は、メインのどこかで定期的に出力ストリームの状態を検査する方法です。そこで、エラーが起こっていることがわかれば、何らかの処理を行います。この章では、文字列を出力してプログラムを中止させる関数 error をユーザーが定義しているものとして説明します。error は事前定義された関数ではありません。error 関数の例は、「14.3.9 入力エラーの処理」を参照してください。iostream の状態を調べるには、演算子 ! を使用 します。iostream がエラー状態の場合はゼロ以外の値を返します。たとえば、次のようにします。
if (!cout) error("output error"); |
エラーを調べるにはもう 1 つの方法があります。ios クラスでは、operator void *() が定義されており、エラーが起こった場合は NULL ポインタを返します。したがって、次の文でエラーを検査できます。
if (cout << x) return; // return if successful |
また、次のように ios クラスのメンバー関数 good を使用することもできます。
if (cout.good()) return; // return if successful |
enum io_state {goodbit=0, eofbit=1, failbit=2, badbit=4, hardfail=0x80}; |
エラー関数の詳細については、iostream のマニュアルページを参照してください。
多くの入出力ライブラリと同様、iostream も出力データを蓄積し、より大きなブロックにまとめて効率よく出力します。出力バッファーをフラッシュする場合、次のように特殊な値 flush を挿入するだけでフラッシュできます。たとえば、次のようにします。
cout << "This needs to get out immediately." << flush; |
flush は、マニピュレータと呼ばれるタイプのオブジェクトの 1 つです。マニピュレータを iostream に挿入すると、その値が出力されるのではなく、何らかの効果が引き起こされます。マニピュレータは実際には関数で、ostream& または istream& を引数として受け取り、そのストリームに対する何らかの動作を実行したあとにその引数を返します。「14.7 マニピュレータ」を参照してください。
ある値をバイナリ形式のままで出力するには、次の例のようにメンバー関数 write を使用します。次の例では、x の値がバイナリ形式のまま出力されます。
cout.write((char*)&x, sizeof(x)); |
この例では、&x を char* に変換しており、型変換の規則に反します。通常このようにしても問題はありませんが、x の型が、ポインタ、仮想メンバー関数、またはコンストラクタの重要な動作を要求するものを持つクラスの場合、前述の例で出力した値を正しく読み込むことができません。
iostream を使用した入力は、出力と同じです。入力には、抽出演算子 >> を使用します。挿入演算子と同様に繰り返し指定できます。たとえば、次のようにします。
cin >> a >> b; |
この例では、標準入力から 2 つの値が取り出されます。ほかの多重定義演算子と同様に、使用される抽出子の機能は a と b (a と b の型が異なれば、別の抽出子が使用されます) の型によって決まります。入力データのフォーマットとその制御方法についての詳細は、ios(3CC4) のマニュアルページを参照してください。通常は、先頭の空白文字 (スペース、改行、タブ、フォームフィードなど) は無視されます。
ユーザーが新たに定義した型のデータを入力するには、出力のために挿入演算子を多重定義したのと同様に、その型に対する抽出演算子を多重定義します。
クラス string の抽出演算子は次のコーディング例のように定義します。
istream& operator>> (istream& istr, string& input) { const int maxline = 256; char holder[maxline]; istr.get(holder, maxline, ”\n’); input = holder; return istr; } |
get 関数は、入力ストリーム istr から文字列を読み取ります。読み取られた文字列は、maxline-1 バイトの文字が読み込まれる、新しい行に達する、EOF に達する、のうちのいずれかが発生するまで、holder に格納されます。データ holder は NULL で終わります。最後に、holder 内の文字列がターゲットの文字列にコピーされます。
規則に従って、抽出子は第 1 引数 (前述の例では istream& istr) から取り出した文字列を変換し、常に参照引数である第 2 引数に格納し、第 1 引数を返します。抽出子とは、入力値を第 2 引数に格納するためのものなので、第 2 引数は必ず参照引数である必要があります。
この定義済み抽出子は問題が起こる可能性があるため、ここで説明しておきます。この抽出子は次のように使用します。
char x[50]; cin >> x; |
前述の例で、抽出子は先頭の空白を読み飛ばし、次の空白文字までの文字列を抽出して x にコピーします。次に、文字列の最後を示す NULL 文字 (0) を入れて文字列を完成します。ここで、入力文字列が指定した配列からあふれる可能性があることに注意してください。
さらに、ポインタが、割り当てられた記憶領域を指していることを確認する必要があります。次に示すのは、よく発生するエラーの例です。
char * p; // not initialized cin >> p; |
入力データが格納される場所が特定されていません。これによって、プログラムが異常終了することがあります。
char 型の抽出子を使用することに加えて、次に示すいずれかの形式でメンバー関数 get を使用することによって、1 文字を読み取ることができます。たとえば、次のようにします。
char c; cin.get(c); // leaves c unchanged if input fails int b; b = cin.get(); // sets b to EOF if input fails |
ほかの抽出子とは異なり、char 型の抽出子は行頭の空白を読み飛ばしません。
空白だけを読み飛ばして、タブや改行などそのほかの文字を取り出すようにするには、次のようにします。
int a; do { a = cin.get(); } while(a ==’ ’); |
メンバー関数 write で出力したようなバイナリの値を読み込むには、メンバー関数 read を使用します。次の例では、メンバー関数 read を使用して x のバイナリ形式の値をそのまま入力します。次の例は、先に示した関数 write を使用した例と反対のことを行います。
cin.read((char*)&x, sizeof(x)); |
メンバー関数 peek を使用するとストリームから次の文字を抽出することなく、その文字を知ることができます。たとえば、次のようにします。
if (cin.peek()!= c) return 0; |
デフォルトでは、iostream の抽出子は先頭の空白を読み飛ばします。 skip フラグをオフにすれば、先頭の空白を読み飛ばさないようにできます。次の例では、 cin の先頭の空白の読み飛ばしをいったんオフにし、のちにオンに戻しています。
cin.unsetf(ios::skipws); // turn off whitespace skipping ... cin.setf(ios::skipws); // turn it on again |
iostream のマニピュレータ ws を使用すると、空白の読み飛ばしが現在オンかオフかに関係なく、iostream から先頭の空白を取り除くことができます。次の例では、iostream istr から先頭の空白が取り除かれます。
istr >> ws; |
通常は、第 1 引数が非ゼロのエラー状態にある場合、抽出子は入力ストリームからのデータの抽出とエラービットのクリアを行わないでください。データの抽出に失敗した場合、抽出子は最低 1 つのエラービットを設定します。
出力エラーの場合と同様、エラー状態を定期的に検査し、非ゼロの状態の場合は処理の中止など何らかの動作を起こす必要があります。! は、iostream のエラー状態を検査します。たとえば次のコーディング例では、英字を入力すると入力エラーが発生します。
#include <stdlib.h> #include <iostream.h> void error (const char* message) { cerr << message << "\n"; exit(1); } int main() { cout << "Enter some characters: "; int bad; cin >> bad; if (!cin) error("aborted due to input error"); cout << "If you see this, not an error." << "\n"; return 0; } |
クラス ios には、エラー処理に使用できるメンバー関数があります。詳細はマニュアルページを参照してください。
C++ プログラムでも stdio を使用できますが、プログラムで iostream と stdio とを標準ストリームとして併用すると、問題が起こる場合があります。たとえば stdout と cout の両方に書き込んだ場合、個別にバッファリングされるため出力結果が設計したとおりにならないことがあります。stdin と cin の両方から入力した場合、問題はさらに深刻です。個別にバッファリングされるため、入力データが使用できなくなってしまいます。
標準入力、標準出力、標準エラーに関するこのような問題を解決するためには、入出力に先立って次の命令を実行します。次の命令で、すべての定義済み iostream が、それぞれ対応する定義済み stdio FILE に結合されます。
ios::sync_with_stdio(); |
このような結合を行うと、定義済みストリームが結合されたものの一部となってバッファリングされなくなってかなり効率が悪くなるため、デフォルトでは結合されていません。同じプログラムでも、stdio と iostream を別のファイルに対して使用することはできます。すなわち、stdio ルーチンを使用して stdout に書き込み、iostream に結合した別のファイルに書き込むことは可能です。また stdio FILE を入力用にオープンしても、stdin から入力しないかぎりは cin からも読み込むことができます。
定義済みの iostream 以外のストリームを読み込む、あるいは書き込む場合は、ユーザーが自分で iostream を生成する必要があります。これは一般には、iostream ライブラリで定義されている型のオブジェクトを生成することになります。ここでは、使用できるさまざまな型について説明します。
ファイル操作は標準入出力の操作に似ています。ifstream、ofstrea m、fstream の 3 つのクラスはそれぞれ、istream、ostream、iostream の各クラスから派生しています。この 3 つのクラスは派生クラスなので、挿入演算と抽出演算、および、そのほかのメンバー関数を継承しており、ファイル使用のためのメンバーとコンストラクタも持っています。
fstream のいずれかを使用するときは、fstream.h をインクルードします。入力だけ行うときは ifstream、出力だけ行うときは ofstream、入出力を行うときは fstream を使用します。コンストラクタへの引数としてはファイル名を渡します。
thisFile というファイルから thatFile というファイルへのファイルコピーを行うときは、次のコーディング例のようになります。
ifstream fromFile("thisFile"); if (!fromFile) error("unable to open ’thisFile’ for input"); ofstream toFile ("thatFile"); if (!toFile) error("unable to open ’thatFile’ for output"); char c; while (toFile && fromFile.get(c)) toFile.put(c); |
このコードでは次のことを実行します。
fromFile という ifstream オブジェクトをデフォルトモード ios::in で生成し、それを thisFile に結合します。thisFile をオープンします。
新しい ifstream オブジェクトのエラー状態を調べ、エラーであれば関数 error を呼び出します。関数 error は、プログラムの別の場所で定義されている必要があります。
toFile という ofstream オブジェクトをデフォルトモード ios::out で生成し、それを thatFile に結合します。
上記のように、toFile のエラー状態を検査します。
データの受け渡しに使用する char 型変数を生成します。
fromFile の内容を一度に 1 文字ずつ toFile にコピーします。
ファイルの内容を一度に 1 文字ずつコピーすることは実際にはあまり行われません。このコードは fstream の使用例として示したにすぎません。実際には、入力ストリームに関係付けられた streambuf を出力ストリームに挿入するのが一般的です。「14.10 streambuf」 と、sbufpub(3CC4) のマニュアルページを参照してください。
オープンモードは、列挙型 open_mode の各ビットの or で構築されます。open_mode は、ios クラスの公開部であり、次のように定義されています。
enum open_mode {binary=0, in=1, out=2, ate=4, app=8, trunc=0x10, nocreate=0x20, noreplace=0x40}; |
UNIX では binary フラグは必要ありませんが、binary フラグを必要とするシステムとの互換性を保つために提供されています。移植可能なコードにするためには、バイナリファイルをオープンするときに binary フラグを使用する必要があります。
入出力両用のファイルをオープンできます。たとえば次のコードでは、someName という入出力ファイルをオープンして、fstream 変数 inoutFile に結合します。
fstream inoutFile("someName", ios::in|ios::out); |
ファイルを指定せずに fstream の宣言だけを行い、のちにファイルをオープンすることもできます。次の例では出力用の ofstream toFile を作成します。
ofstream toFile; toFile.open(argv[1], ios::out); |
fstream をいったんクローズし、また別のファイルでオープンすることができます。たとえば、コマンド行で与えられるファイルリストを処理するには次のようにします。
ifstream infile; for (char** f = &argv[1]; *f; ++f) { infile.open(*f, ios::in); ...; infile.close(); } |
標準出力は整数 1 などのようにファイル記述子がわかっている場合は、次のようにファイルをオープンできます。
ofstream outfile; outfile.attach(1); |
fstream コンストラクタの 1 つにファイル名を指定してファイルをオープンしたり、open 関数を使用してオープンしたファイルは、fstream が破壊された時点 (delete するか、スコープ外に出る時点) で自動的にクローズされます。attach で fstream に結合したファイルは、自動的にはクローズされません。
ファイル内の読み込み位置と書き込み位置を変更することができます。そのためには次のようなツールがあります。
tellg (tellp) は istream (ostream) のメンバー関数で、現在のファイル内の位置を返します。istream と ostream は fstream の親クラスであるため、tellg と tellp も fstream クラスのメンバー関数として呼び出すことができます。
seekg (seekp) は istream (ostream) のメンバー関数で、指定したファイル内の位置を探し出します。
enum seek_dir は、seek での相対位置を指定します。
enum seek_dir {beg=0, cur=1, end=2}; |
fstream aFile の位置再設定の例を次に示します。
streampos original = aFile.tellp(); //save current position aFile.seekp(0, ios::end); //reposition to end of file aFile << x; //write a value to file aFile.seekp(original); //return to original position |
seekg (seekp) は、1 つまたは 2 つの引数を受け取ります。引数を 2 つ受け取るときは、第 1 引数は、第 2 引数で指定した seek_dir 値が示す位置からの相対位置となります。たとえば、次のようにします。
aFile.seekp(-10, ios::end); |
この例では、ファイルの最後から 10 バイトの位置に設定されます。
aFile.seekp(10, ios::cur); |
一方、次の例では現在位置から 10 バイト進められます。
テキストストリーム上での任意位置へのシーク動作はマシン依存になります。ただし、以前に保存した streampos の値にいつでも戻ることができます。
iostream では、あるストリームを別のストリームに代入することはできません。
ストリームオブジェクトをコピーすると、出力ファイル内の現在の書き込み位置ポインタなどの位置情報が二重に存在するようになり、それを個別に変更できるという状態が起こります。これは、ストリーム操作を混乱させる可能性があります。
フォーマットの制御については、ios(3CC4) のマニュアルページで詳しく説明しています。
マニピュレータとは、iostream に挿入したり、iostream から抽出したりする値で特別な効果があります。
引数付きマニピュレータとは、1 つ以上の追加の引数を持つマニピュレータのことです。
マニピュレータは通常の識別子であるため、マニピュレータの定義を多く行うと可能な名前を使いきってしまうので、iostream では考えられるすべての機能に対して定義されているわけではありません。マニピュレータの多くは、この章の別の箇所でメンバー関数とともに説明しています。
表 14–2 の説明どおり、定義済みマニピュレータは 13 個あります。この表で使用している文字の意味は次のとおりです。
i は long 型です。
n は int 型です。
c は char 型です。
istr は 入力ストリームです。
ostr は 入力ストリームです。
|
定義済みマニピュレータ |
内容の説明 |
---|---|---|
1 |
ostr << dec, istr >> dec | |
2 |
ostr << endl | |
3 |
ostr << ends | |
4 |
ostr << flush | |
5 |
ostr << hex, istr >> hex | |
6 |
ostr << oct, istr >> oct | |
7 |
istr >> ws | |
8 |
ostr << setbase(n)、istr >> setbase(n) | |
9 |
ostr << setw(n), istr >> setw(n) | |
10 |
ostr << resetiosflags(i), istr>> resetiosflags(i) | |
11 |
ostr << setiosflags(i), istr >> setiosflags(i) | |
12 |
ostr << setfill(c), istr >> setfill(c) | |
13 |
ostr << setprecision(n), istr >> setprecision(n) |
定義済みマニピュレータを使用するには、プログラムにヘッダーファイル iomanip.h をインクルードする必要があります。
ユーザーが独自のマニピュレータを定義することもできます。マニピュレータには次の 2 つの基本タイプがあります。
引数なしのマニピュレータ istream&、ostream&、ios& のいずれかを引数として受け取り、ストリームの操作が終わるとその引数を返します。
引数付きのマニピュレータ istream&、ostream&、ios& のいずれかと、そのほかもう 1 つの引数 (追加の引数) を受け取り、ストリームの操作が終わるとストリーム引数を返します。次に、それぞれのタイプのマニピュレータの例を示します。
引数なしのマニピュレータは、次の 3 つを実行する関数です。
ストリームの参照引数を受け取ります。
そのストリームに何らかの処理を行います。
その引数を返します。
iostream では、このような関数 (へのポインタ) を使用するシフト演算子がすでに定義されていますので、関数を入出力演算子シーケンスの中に入れることができます。シフト演算子は、値の入出力を行う代わりに、その関数を呼び出します。tab を ostream に挿入する tab マニピュレータの例を示します。
ostream& tab(ostream& os) { return os <<’\t’; } ... cout << x << tab << y; |
次のコードは、前述の例と同じ処理をより洗練された方法で行います。
const char tab = ’\t’; ... cout << x << tab << y; |
次に示すのは別の例で、定数を使用してこれと同じことを簡単に実行することはできません。入力ストリームに対して、空白の読み飛ばしのオン、オフを設定すると仮定します。ios::setf と ios::unsetf を別々に呼び出して、skipws フラグをオンまたはオフに設定することもできますが、次の例のように 2 つのマニピュレータを定義して設定することもできます。
#include <iostream.h> #include <iomanip.h> istream& skipon(istream &is) { is.setf(ios::skipws, ios::skipws); return is; } istream& skipoff(istream& is) { is.unsetf(ios::skipws); return is; } ... int main () { int x,y; cin >> skipon >> x >> skipoff >> y; return 1; } |
iomanip.h に入っているマニピュレータの 1 つに setfill があります。setfill は、フィールド幅に詰め合わせる文字を設定するマニピュレータで、次の例に示すように定義されています。
//file setfill.cc #include<iostream.h> #include<iomanip.h> //the private manipulator static ios& sfill(ios& i, int f) { i.fill(f); return i; } //the public applicator smanip_int setfill(int f) { return smanip_int(sfill, f); } |
引数付きマニピュレータは、2 つの部分から構成されます。
1 つはマニピュレータ部分で、これは引数を 1 つ追加します。この前の例では、int 型の第 2 引数があります。このような関数に対するシフト演算子は定義されていませんので、このマニピュレータ関数を入出力演算子シーケンスに入れることはできません。そこで、マニピュレータの代わりに補助関数 (適用子) を使用する必要があります。
適用子。これはマニピュレータを呼び出します。適用子は大域関数で、そのプロトタイプをヘッダーファイルに入れておきます。マニピュレータは通常、適用子の入っているソースコードファイル内に静的関数として作成します。マニピュレータは適用子からのみ呼び出されるので、静的関数にして、大域アドレス空間にマニピュレータ関数名を入れないようにします。
ヘッダーファイル iomanip.h には、さまざまなクラスが定義されています。各クラスには、マニピュレータ関数のアドレスと 1 つの引数の値が入っています。iomanip クラスについては、manip(3CC4) のマニュアルページで説明しています。この前の例では、smanip_int クラスを使用しており、ios で使用できます。ios で使用できるということは、istream と ostream でも使用できるということです。この例ではまた、int 型の第 2 引数を使用しています。
適用子は、クラスオブジェクトを作成してそれを返します。この前の例では、smanip_int というクラスオブジェクトが作成され、そこにマニピュレータと、適用子の int 型引数が入っています。ヘッダーファイル iomanip.h では、このクラスに対するシフト演算子が定義されています。入出力演算子シーケンスの中に適用子関数 setfill があると、その適用子関数が呼び出され、クラスが返されます。シフト演算子はそのクラスに対して働き、クラス内に入っている引数値を使用してマニピュレータ関数が呼び出されます。
次の例では、マニピュレータ print_hex は次のことを行います。
この例は出力専用のため、omanip_long クラスが使用されています。また、int 型でなく long 型でデータを操作します。
#include <iostream.h> #include <iomanip.h> static ostream& xfield(ostream& os, long v) { long save = os.setf(ios::hex, ios::basefield); os << v; os.setf(save, ios::basefield); return os; } omanip_long print_hex(long v) { return omanip_long(xfield, v); } |
strstream(3CC4) のマニュアルページを参照してください。
stdiobuf(3CC4) のマニュアルページを参照してください。
入力や出力のシステムは、フォーマットを行う iostream と、フォーマットなしの文字ストリームの入力または出力を行う streambuf からなります。
通常は iostream を経由して streambuf を使用するため、streambuf の詳細について意識する必要はありません。たとえば、効率を改善する必要がある場合や、エラー処理を回避する場合、iostream に書式を構築する場合は、streambuf を直接使用できます。
streambuf は文字シーケンス (文字ストリーム) と、シーケンス内を指す 1 つまたは 2 つのポインタとで構成されています。各ポインタは文字と文字の間を指しています。実際には文字と文字の間を指しているわけではありませんが、このように考えておくと理解しやすくなります。streambuf ポインタには次の種類があります。
streambuf は、このどちらかのポインタ、または両方のポインタを持ちます。
ポインタ位置の操作とシーケンスの内容の操作にはさまざまな方法があります。文字列の操作時に両方のポインタが移動するかどうかは、使用される streambuf の種類によって違います。一般に、キュー形式の streambuf の場合は、get ポインタと put ポインタは別々に移動し、ファイル形式の streambuf の場合は、get ポインタと put ポインタは同時に移動します。キュー形式ストリームの例としては strstream があり、ファイル形式ストリームの例としては fstream があります。
ユーザーは streambuf オブジェクト自体を作成することはなく、streambuf クラスから派生したクラスのオブジェクトを作成します。その例として、filebuf と strstreambuf とがあります。この 2 つについてはそれぞれ filebuf(3CC4) および ssbuf(3) のマニュアルページを参照してください。より高度な使い方として、独自のクラスを streambuf から派生させて特殊デバイスのインタフェースを提供したり、基本的なバッファリング以外のバッファリングを行なったりすることができます。sbufpub(3CC4) と sbufprot (3CC4) のマニュアルページでは、それらの方法に ついて説明しています。
ユーザー用の特殊な streambuf を作成するとき以外にも、前述のマニュアルページで説明しているように、iostream と結合した streambuf にアクセスして公開メンバー関数を使用する場合があります。また、各 iostream には、streambuf へのポインタを引数とする定義済みの挿入子と抽出子があります。streambuf を挿入したり抽出したりすると、ストリーム全体がコピーされます。
次の例では、先に説明したファイルコピーとは違う方法でファイルをコピーしています。
ifstream fromFile("thisFile"); ofstream toFile ("thatFile"); toFile << fromFile.rdbuf(); |
入力ファイルと出力ファイルは、前述の例と同じ方法でオープンします。各 iostream クラスにはメンバー関数 rdbuf があり、それに結合した streambuf オブジェクトへのポインタを返します。fstream の場合、streambuf オブジェクトは filebuf 型です。fromFile に結合したファイル全体が toFile に結合したファイルにコピー (挿入) されます。最後の行は次のように書くこともできます。
fromFile >> toFile.rdbuf(); |
前述の書き方では、ソースファイルが抽出されて目的のところに入ります。どちらの書き方をしても、結果はまったく同じになります。
C++ では、iostream ライブラリの詳細を説明する多くのマニュアルページがあります。次に、各マニュアルページの概要を示します。
従来型の iostream ライブラリのマニュアルページを表示するには、次のように入力します (name には、マニュアルページのトピック名を入力)。
example% man -s 3CC4 name |
iostream ライブラリの説明では、一般のプログラミングに関する用語と同じでも意味が異なる語を多く使用します。次の表では、それらの用語が iostream ライブラリの説明で使用される場合の意味を定義します。
表 14–4 iostream の用語
iostream 用語 |
定義 |
---|---|
バッファーには、2 つの意味があります。1 つは iostream パッケージに固有のバッファーで、もう 1 つは入出力一般に適用されるバッファーです。 iostream ライブラリに固有のバッファーは、streambuf クラスで定義されたオブジェクトです。 一般にいうバッファーは、入出力データを効率よく転送するために使用するメモリーブロックを指します。バッファリングされた入出力の場合は、バッファーがいっぱいになるか、バッファーが強制的にフラッシュされるときまで、データの転送は行われません。 「バッファリングなしのバッファー」とは、前述で定義したように一般にいうバッファーがない streambuf を指します。この章では、streambuf を指す「バッファー」という用語を使用することを避けています。ただし、マニュアルページや C++ の他のドキュメントでは、 streambuf を意味する「バッファー」という用語を使用しています。 |
|
iostream から入力データを取り出す操作を抽出といいます。 |
|
ファイル用に特殊化された入出力ストリームです。特に courier のようにクーリエフォントで印刷されている場合は、iostream クラスから派生したクラスを指します。 |
|
iostream に出力データを送り込む操作を挿入といいます。 |
|
一般には、入力ストリームまたは出力ストリームです。 |
|
iostream ライブラリ |
ファイル iostream.h、fstream.h、strstream.h、iomanip.h、ライブラリ stdiostream.h をインクルードすることにより使用できるライブラリです。iostream はオブジェクト指向のライブラリであるため、ユーザーが必要に応じて拡張できます。そのため、iostream ライブラリを使用して実行できるすべての機能があらかじめ定義されているわけではありません。 |
一般に、iostream、fstream、strstream、またはユーザー定義のストリームをいいます。 |
|
文字シーケンスの入ったバッファーで、put ポインタまたは get ポインタ、あるいはその両方を持ちます。courier のようにクーリエフォントで印刷されている場合は、特定のクラスを意味します。そのほかのフォントで印刷されている場合は一般に streambuf クラスのオブジェクト、または streambuf の派生クラスを意味します。ストリームオブジェクトは必ず、streambuf から派生した型のオブジェクト (またはそのオブジェクトへのポインタ) を持っています。 |
|
文字型配列処理用に特殊化した iostream です。courier のようにクーリエフォントで印刷されている場合は、特定のクラスを意味します。 |
複素数には「実部」と「虚部」があります。たとえば、次のようにします。
3.2 + 4i 1 + 3i 1 + 2.3i
縮退の場合、0 + 3i のように完全に虚部だけのものは通常 3i と書き込み、5 + 0i のように完全に実部だけのものは通常 5 と書き込みます。データ型 complex を使用すると複素数を表現できます。
複素数ライブラリ (libcomplex) は互換モードでのみ使用できます (-compat[=4])。 標準モード (デフォルトのモード) では、同様の機能を持つ複素数クラスが C++ 標準ライブラリ (libCstd) に含まれています。
複素数ライブラリは、新しいデータ型として複素数データ型を実装します。このライブラリには次のものが含まれています。
演算子
数学関数 (組み込み数値型用に定義されている関数)
拡張機能 (複素数の入出力を可能にする iostream 用)
エラー処理機能
複素数には、実部と虚部による表現方法のほかに、 絶対値と偏角による表現方法があります。複素数ライブラリには、実部と虚部によるデカルト表現と、絶対値と偏角による極座標表現とを互いに変換する関数も提供しています。
共役複素数は、虚部の符号が反対の複素数です。
複素数ライブラリを使用する場合は、プログラムにヘッダーファイル complex.h をインクルードし、-lcomplex オプションまたは -library=complex オプションを使用してリンクしてください。
複素数ライブラリでは、クラス complex が 1 つだけ定義されています。クラス complex のオブジェクトは、1 つの複素数を持つことができます。複素数は次の 2 つの部分で構成されています。
実部
虚部
class complex { double re, im; }; |
クラス complex のオブジェクトの値は、1 組の double 型の値です。最初の値が実部を表し、2 番目の値が虚部を表します。
complex には 2 つのコンストラクタがあります。それぞれの定義を次に示します。
complex::complex() {re=0.0; im=0.0;} complex::complex(double r, double i = 0.0) {re=r; im=i;} |
複素数の変数を引数なしで宣言すると、最初のコンストラクタが使用され、実部も虚部もゼロで初期化されます。次の例では、実部も虚部もゼロの複素数の変数が生成されます。
complex aComp; |
1 つまたは 2 つのパラメータを指定できます。いずれの場合にも、2 番目のコンストラクタが使用されます。引数を 1 つだけ指定した場合は、その値は実部の値とみなされ虚部はゼロに設定されます。たとえば、次のようにします。
complex aComp(4.533); |
複素数の値は次のようになります。
4.533 + 0i |
引数を 2 つ指定した場合は、最初の値が実部、2 番目の値が虚部となります。たとえば、次のようにします。
complex aComp(8.999, 2.333); |
複素数の値は次のようになります。
8.999 + 2.333i |
また、複素数ライブラリが提供する polar 関数を使用して複素数を生成することもできます。「15.3 数学関数」を参照してください。polar 関数は、指定した 1 組の極座標値 (絶対値と偏角) を使用して複素数を作成します。
complex 型にはデストラクタはありません。
複素数ライブラリでは、すべての基本算術演算子が定義されています。特に、次の 5 つの演算子は通常の型の演算と同様に使用することができ、優先順序も同じです。
+ - / * =
演算子 - は、通常の型の場合と同様に 2 項演算子としても単項演算子としても使用できます。
このほか、次の演算子の使用方法も通常の型で使用する演算子と同様です。
加算代入演算子 (+=)
減算代入演算子 (-=)
乗算代入演算子 (*=)
除算代入演算子 (/=)
ただし、この 4 つの演算子については、式の中で使用可能な値は生成されません。したがって、次のコードは機能しません。
complex a, b; ... if ((a+=2)==0) {...}; // illegal b = a *= b; // illegal |
また、等しいか否かを判定する 2 つの演算子 (==、!=) は、通常の型で使用する演算子と同様に使用することができます。
算術式で実数と複素数が混在しているときは、C++ では複素数のための演算子関数が使用され、実数は複素数に変換されます。
複素数ライブラリには、多くの数学関数が含まれています。複素数に特有のものもあれば、C の標準数学ライブラリの関数と同じで複素数を対象にしたものもあります。
これらの関数はすべて、あらゆる可能な引数に対して結果を返します。関数が数学的に正しい結果を返せないような場合は、complex_error を呼び出して、何らかの適切な値を返します。たとえば、関数はオーバーフローが実際に起こるのを避け、代わりにメッセージで complex_error を呼び出します。次の表で複素数ライブラリの関数を説明します。
sqrt 関数と atan2 関数は、C99 の csqrt (Annex G) の仕様に従って実装されています。
複素数ライブラリ関数 |
内容の説明 |
---|---|
double abs(const complex) |
複素数の絶対値を返します。 |
double arg(const complex) |
複素数の偏角を返します。 |
complex conj(const complex) |
引数に対する共役複素数を返します。 |
double imag(const complex&) |
複素数の虚部を返します。 |
double norm(const complex) |
引数の絶対値の 2 乗を返します。abs より高速ですが、オーバーフローが起きやすくなります。絶対値の比較に使用します。 |
complex polar(double mag, double ang=0.0) |
複素数の絶対値と偏角を表す一組の極座標を引数として受け取り、それに対応する複素数を返します。 |
double real(const complex&) |
複素数の実部を返します。 |
表 15–2 複素数の数学関数と三角関数
内容の説明 |
|
---|---|
complex acos(const complex) |
引数が余弦となるような角度を返します。 |
complex asin(const complex) |
引数が正弦となるような角度を返します。 |
complex atan(const complex) |
引数が正接となるような角度を返します。 |
complex cos(const complex) |
引数の余弦を返します。 |
complex cosh(const complex) |
引数の双曲線余弦を返します。 |
complex exp(const complex) |
e**x を計算します。ここで e は自然対数の底で、x は関数 exp に渡された引数です。 |
complex log(const complex) |
引数の自然対数を返します。 |
complex log10(const complex) |
引数の常用対数を返します。 |
complex pow(double b, const complex exp) complex pow(const complex b, int exp) complex pow(const complex b, double exp) complex pow(const complex b, const complex exp) |
引数を 2 つ持ちます。pow(b, exp).b を exp 乗します。 |
complex sin(const complex) |
引数の正弦を返します。 |
complex sinh(const complex) |
引数の双曲線正弦を返します。 |
complex sqrt(const complex) |
引数の平方根を返します。 |
complex tan(const complex) |
引数の正接を返します。 |
complex tanh(const complex) |
引数の双曲線正接を返します。 |
複素数ライブラリでは、エラー処理が次のように定義されています。
extern int errno; class c_exception {...}; int complex_error(c_exception&); |
外部変数 errno は C ライブラリの大域的なエラー状態です。errno は、標準ヘッダー errno.h (perror(3) のマニュアルページを参照) にリストされている値を持ちます。errno には、多くの関数でゼロ以外の値が設定されます。
ある特定の演算でエラーが起こったかどうか調べるには、次のようにしてください。
演算実行前に errno をゼロに設定する。
演算終了後に値を調べる。
関数 complex_error は c_exception 型の参照引数を持ち、次に示す複素数ライブラリ関数に呼び出されます。
exp
log
log10
sinh
cosh
デフォルトの complex_error はゼロを返します。ゼロが返されたということは、デフォルトのエラー処理が実行されたということです。ユーザーは独自の complex_error 関数を作成して、別のエラー処理を行うことができます。エラー処理については、cplxerr(3CC4) のマニュアルページで説明しています。
デフォルトのエラー処理については、cplxtrig(3CC4) と cplxexp(3CC4) のマニュアルページを参照してください。次の表にも、その概要を掲載しています。
複素数ライブラリ関数 |
デフォルトエラー処理 |
---|---|
exp | |
log、log10 | |
sinh、cosh |
引数の虚部によりオーバーフローが起こる場合は複素数ゼロを返します。引数の実部によりオーバーフローが起こる場合は最大複素数を返します。どちらの場合も errno は ERANGE に設定されます。 |
d複素数ライブラリでは、次の例に示す複素数のデフォルトの抽出子と挿入子が提供されています。
ostream& operator<<(ostream&, const complex&); //inserter istream& operator>>(istream&, complex&); //extractor |
抽出子と挿入子の基本的な説明については、「14.2 iostream 操作の基本構造」と「14.3.1 iostream を使用した出力」を参照してください。
入力の場合、複素数の抽出子 >> は、(括弧の中にあり、コンマで区切られた) 一組の値を入力ストリームから抽出し、複素数オブジェクトに読み込みます。最初の値が実部の値、2 番目の値が虚部の値となります。たとえば、次のような宣言と入力文がある場合、
complex x; cin >> x; |
(3.45, 5) と入力すると、複素数 x の値は 3.45 + 5.0i となります。抽出子の場合はこの反対になります。complex x(3.45, 5), cout<<x の場合は、(3.45, 5) と印刷されます。
入力データは、通常括弧の中でコンマで区切られた一組の値で、スペースは入れても入れなくてもかまいません。値を 1 つだけ入力したとき (括弧とスペースは入力してもしなくても同じ) は、抽出子は虚部をゼロとします。シンボル i を入力してはいけません。
挿入子は、複素数の実部と虚部をコンマで区切り、全体を括弧で囲んで挿入します。シンボル i は含まれません。2 つの値は double 型として扱われます。
complex 型は、組み込みの算術型と混在した式でも使用できるように定義されています。算術型は自動的に complex 型に変換されます。算術演算子とほとんどの数学関数の complex バージョンがあります。たとえば、次のようにします。
int i, j; double x, y; complex a, b; a = sin((b+i)/y) + x/j; |
b+i という式は混合算術演算です。整数 i は、コンストラクタ complex::complex(double,double=0) によって、complex 型に変換されます。このとき、まず整数から double 型に変換されます。y、double で割られる計算結果です。つまり、y は complex 型へ変換され、複素数除算演算が使用されます。商もまた complex 型ですので、複素数の正弦関数が呼び出され、その結果も complex 型になります。次も同様です。
ただし、すべての算術演算と型変換が暗黙に行われるわけではありませんし、定義されていないものもあります。たとえば、複素数は数学的な意味での大小関係が決められないので、比較は等しいか否かの判定しかできません。
complex a, b; a == b; // OK a != b; // OK a < b; // error: operator < cannot be applied to type complex a >= b; // error: operator >= cannot be applied to type complex |
同様に、complex 型からそれ以外の型への変換もはっきりした定義ができないので、そのような自動変換は行われません。変換するときは、実部または虚部を取り出すのか、または絶対値を取り出すのかを指定する必要があります。
complex a; double f(double); f(abs(a)); // OK f(a); // error: no match for f(complex) |
クラス complex は効率も考慮して設計されています。
非常に簡単な関数が inline で宣言されており、関数呼び出しのオーバーヘッドをなくしています。
効率に差があるものは、関数が多重定義されています。たとえば、pow 関数には引数が complex 型のもののほかに、引数が double 型と int 型のものがあります。その方が double 型と int 型の計算がはるかに簡単になるからです。
complex.h をインクルードすると、C の標準数学ライブラリヘッダー math.h も自動的にインクルードされます。C++ の多重定義の規則により、次のようにもっとも効率の良い式の評価が行われます。
double x; complex x = sqrt(x); |
この例では、標準数学関数 sqrt(double) が呼び出され、その計算結果が complex 型に変換されます。最初に complex 型に変換され、sqrt(complex) が呼び出されるのではありません。これは、多重定義の解決規則から決まる方法で、もっとも効率の良い方法です。
複素数演算ライブラリの情報は、次のマニュアルページに記載されています。
表 15–3 complex 型のマニュアルページ
マニュアルページ |
概要 |
---|---|
cplx.intro(3CC4) |
複素数ライブラリ全体の紹介 |
cartpol(3CC4) |
直角座標と極座標の関数 |
cplxerr(3CC4) |
エラー処理関数 |
cplxexp(3CC4) |
指数、対数、平方根の関数 |
cplxops(3CC4) |
算術演算子関数 |
cplxtrig(3CC4) |
三角関数 |
この章では、ライブラリの構築方法を説明します。
ライブラリには 2 つの利点があります。まず、ライブラリを使えば、コードをいくつかのアプリケーションで共有できます。共有するコードがある場合は、そのコードを含むライブラリを作成し、コードを必要とするアプリケーションとリンクできます。次に、ライブラリを使えば、非常に大きなアプリケーションの複雑さを軽減できます。アプリケーションの中の、比較的独立した部分をライブラリとして構築および保守することで、プログラマはほかの部分の作業により専念できるようになるためです。
ライブラリの構築とは、.o ファイルを作成し (コードを -c オプションでコンパイルし)、これらの .o ファイルを CC コマンドでライブラリに結合することです。ライブラリには、静的 (アーカイブ) ライブラリと動的 (共有) ライブラリがあります。
静的 (アーカイブ) ライブラリの場合は、ライブラリのオブジェクトがリンク時にプログラムの実行可能ファイルにリンクされます。アプリケーションにとって必要な .o ファイルだけがライブラリから実行可能ファイルにリンクされます。静的 (アーカイブ) ライブラリの名前には、一般的に接尾辞として .a が付きます。
動的 (共有) ライブラリの場合は、 ライブラリのオブジェクトはプログラムの実行可能ファイルにリンクされません。その代わりに、プログラムがこのライブラリに依存することをリンカーが実行可能ファイルに記録します。プログラムが実行されるとき、システムは、プログラムに必要な動的ライブラリを読み込みます。同じ動的ライブラリを使用する 2 つのプログラムが同時に実行されると、ライブラリはこれらのプログラムによって共有されます。動的 (共有) ライブラリの名前には、接尾辞として .so が付きます。
共有ライブラリを動的にリンクすることは、アーカイブライブラリを静的にリンクすることに比べていくつかの利点があります。
実行可能ファイルのサイズが小さくなる
実行時にコードのかなりの部分をプログラム間で共有できるため、メモリーの使用量が少なくなる
アプリケーションをリンクし直さずに、実行時にライブラリを置き換えることができる (これは、プログラムの再リンクおよび再配布の必要なしに、Solaris オペレーティングシステムの多くの改良をプログラムで利用できる主要機構である)
ただし、動的ライブラリには短所もあります。
実行時のリンクに時間がかかる
動的ライブラリを使用するプログラムを配布する場合には、それらのライブラリも同時に配布しなければならないことがある
共有ライブラリを異なる場所に移動すると、システムがライブラリを見つけられず、プログラムを実行できないことがある(この問題は、環境変数 LD_LIBRARY_PATH で解決できる)。
静的 (アーカイブ) ライブラリを構築する仕組みは、実行可能ファイルを構築することに似ています。一連のオブジェクト (.o) ファイルは、CC で -xar オプションを使うことで 1 つのライブラリに結合できます。
静的 (アーカイブ) ライブラリを構築する場合は、ar コマンドを直接使用せずに CC -xar を使用してください。C++ 言語では一般に、従来の .o ファイルに収容できる情報より多くの情報 (特に、テンプレートインスタンス) をコンパイラが持たなければなりません。-xar オプションを使用すると、テンプレートインスタンスを含め、すべての必要な情報がライブラリに組み込まれます。make ではどのテンプレートファイルが実際に作成され、参照されているのかがわからないため、通常のプログラミング環境でこのようにすることは困難です。CC -xar を指定しないと、参照に必要なテンプレートインスタンスがライブラリに組み込まれないことがあります。たとえば、次のようにします。
% CC -c foo.cc # Compile main file, templates objects are created. % CC -xar -o foo.a foo.o # Gather all objects into a library. |
-xar フラグによって、CC が静的 (アーカイブ) ライブラリを作成します。-o 命令は、新しく作成するライブラリの名前を指定するために必要です。コンパイラは、コマンド行のオブジェクトファイルを調べ、これらのオブジェクトファイルと、テンプレートリポジトリで認識されているオブジェクトファイルとを相互参照します。そして、ユーザーのオブジェクトファイルに必要なテンプレートを (本体のオブジェクトファイルとともに) アーカイブに追加します。
既存のアーカイブのみを作成または更新するには、-xar フラグを使用します。このフラグをアーカイブの保守に使用しないでください。-xar オプションは ar -cr を実行するのと同じことです。
1 つの .o ファイルには 1 つの関数を入れることをお勧めします。アーカイブとリンクする場合、特定の .o ファイルのシンボルが必要になると、.o ファイル全体がアーカイブからアプリケーションにリンクされます。.o ファイルに 1 つの関数を入れておけば、アプリケーションにとって必要なシンボルだけがアーカイブからリンクされます。
動的 (共有) ライブラリの構築方法は、コマンド行に -xar の代わりに -G を指定することを除けば、静的 (アーカイブ) ライブラリの場合と同じです。
ld は直接使用しないでください。静的ライブラリの場合と同じように、CC コマンドを使用すると、必要なすべてのテンプレートインスタンスがテンプレートリポジトリからライブラリに組み込まれます (テンプレートを使用している場合)。アプリケーションにリンクされている動的ライブラリでは、すべての静的コンストラクタは main() が実行される前に呼び出され、すべての静的デストラクタは main() が終了したあとに呼び出されます。dlopen() で共有ライブラリを開いた場合、すべての静的コンストラクタは dlopen() で実行され、すべての静的デストラクタは dlclose() で実行されます。
動的ライブラリを構築するには、必ず CC に -G を使用します。ld (リンクエディタ) または cc (C コンパイラ) を使用して動的ライブラリを構築すると、例外が機能しない場合があり、ライブラリに定義されている大域変数が初期化されません。
動的 (共有) ライブラリを構築するには、 CC の -Kpic や -KPIC オプションで各オブジェクトをコンパイルして、再配置可能なオブジェクトファイルを作成する必要があります。次に、これらの再配置可能オブジェクトファイルから動的ライブラリを構築します。原因不明のリンクエラーが出る場合は、-Kpic や -KPIC でコンパイルしていないオブジェクトがある可能性があります。
ソースファイル lsrc1.cc と lsrc2.cc から作成するオブジェクトファイルから C++ 動的ライブラリ libfoo.so を構築するには、次のようにします。
% CC -G -o libfoo.so -h libfoo.so -Kpic lsrc1.cc lsrc2.cc |
-G オプションは、動的ライブラリの構築を指定しています。-o オプションは、ライブラリのファイル名を指定しています。-h オプションは、共有ライブラリの内部名を指定しています。-Kpic オプションは、オブジェクトファイルが位置に依存しないことを指定しています。
CC -G コマンドは -l オプションをリンカー ld に渡しません。初期化順序が必ず正しくなるようにするには、共有ライブラリに自らが必要とするほかの各共有ライブラリとの明示的な依存関係を設定する必要があります。依存関係を作成するには、該当するライブラリごとに -l オプションを使用します。標準的な C++ 共有ライブラリは、次の一群のオプションのうち 1 つを使用します。
-lCstd -lCrun -lc -library=stlport4 -lCrun -lc |
必要とされるすべての依存関係をリストしたことを確認するには、-zdefs オプションを指定してライブラリを構築します。不明のシンボル定義ごとに、リンカーはエラーメッセージを生成します。不明の定義を指定するには、それらのライブラリに -l オプションを追加します。
不要な依存関係を含んでいるかどうか検索するには、次のコマンドを使用します。
ldd -u -r mylib.so ldd -U -r mylib.so |
その後、不要な依存関係を除外し、mylib.so を再構築できます。
C++ コードが含まれているプログラムでは、-Bsymbolic を使用せずに、リンカーのマップファイルを使用してください。-Bsymbolic を使用すると、異なるモジュール内の参照が、本来 1 つの大域オブジェクトの複数の異なる複製に結合されてしまう可能性があります。
例外メカニズムは、アドレスの比較によって機能します。オブジェクトの複製が 2 つある場合は、アドレスが同一であると評価されず、本来一意のアドレスを比較することで機能する例外メカニズムで問題が発生することがあります。
ある組織の内部でしか使用しないライブラリを構築する場合には、一般的な使用には適さないオプションを使ってライブラリを構築することもできます。具体的には、ライブラリはシステムのアプリケーションバイナリインタフェース (ABI) に準拠していなくてもかまいません。たとえば、ライブラリを -fast オプションでコンパイルして、特定のアーキテクチャー上でのパフォーマンスを向上させることができます。同じように、-xregs=float オプションでコンパイルして、パフォーマンスを向上させることもできます。
ほかの組織からも使用できるライブラリを構築する場合は、ライブラリの管理やプラットフォームの汎用性などの問題が重要になります。ライブラリを公開にするかどうかを決める簡単な基準は、アプリケーションのプログラマがライブラリを簡単に再コンパイルできるかどうかということです。公開ライブラリは、システムの ABI に準拠して構築しなければなりません。一般に、これはプロセッサ固有のオプションを使用しないということを意味します。たとえば、-fast や -xtarget は使用しないようにします。
SPARC ABI では、いくつかのレジスタがアプリケーション専用で使用されます。V7 と V8 では、これらのレジスタは %g2、%g3、%g4 です。V9 では、これらのレジスタは %g2 と %g3 です。ほとんどのコンパイルはアプリケーション用に行われるので、C++ コンパイラは、デフォルトでこれらのレジスタを一時レジスタに使用して、プログラムのパフォーマンスを向上しようとします。しかし、公開ライブラリでこれらのレジスタを使用することは、SPARC ABI に適合しないことになります。公開ライブラリを構築するときには、アプリケーションレジスタを使用しないようにするために、すべてのオブジェクトを -xregs=no%appl オプションで コンパイルしてください。
C++ で作成されたライブラリを C プログラムから使用できるようにするには、C API を作成する必要があります。そのためには、エクスポートされるすべての関数を extern "C" にします。ただし、これができるのは大域関数だけで、メンバー関数にはできません。
C インタフェースライブラリで C++ の実行時サポートを必要とし、しかも cc とリンクしている場合は、C インタフェースライブラリを使用するときにアプリケーションも libC (互換モード) または libCrun (標準モード) にリンクする必要があります。C インタフェースライブラリで C++ 実行時サポートが不要の場合は、libC や libCrun とリンクする必要はありません。リンク手順は、アーカイブされたライブラリと共有ライブラリでは異なります。
アーカイブされた C インタフェースライブラリを提供するときは、ライブラリの使用方法を説明する必要があります。
C インタフェースライブラリが CC を標準モード (デフォルト) で構築している場合は、C インタフェースライブラリを使用するときに -lCrun を cc コマンド行に追加します。
C インタフェースライブラリが CC を互換モード (-compat) で構築している場合は、C インタフェースライブラリを使用するときに -lC を cc コマンド行に追加します。
共有 C インタフェースライブラリを提供するときは、ライブラリの構築時に libC または libCrun と依存関係をつくる必要があります。共有ライブラリの依存関係が正しければ、ライブラリを使用するときに -lC または -lCrun をコマンド行に追加する必要はありません。
C インタフェースライブラリを互換モード (-compat) で構築している場合は、-lC インタフェースライブラリの構築時に -lC を CC コマンド行に追加します。
C インタフェースライブラリを標準モード (デフォルト) で構築している場合は、C インタフェースライブラリの構築時に -lCrun を cc ではなく CC コマンド行に追加します。
さらに、C++ 実行時ライブラリにもまったく依存しないようにするには、ライブラリソースに対して次のコーディング規則を適用する必要があります。
どのような形式の new もしくは delete も使用しない (独自の new または delete を定義する場合は除く)
例外を使用しない
実行時の型識別機構 (RunTime Type Information、RTTI) を使用しない
C プログラムから dlopen() で C++ 共有ライブラリを開く場合は、共有ライブラリが適切な C++ 実行時ライブラリ (-compat=4 の場合は libC.so.5、-compat=5 の場合は libCrun.so.1) に依存していることを確認してください。
そのためには、共有ライブラリの構築時に、-compat=4 の場合は -lC、-compat=5 の場合は -lCrun を次のようにコマンド行に追加します。たとえば、次のようにします。
example% CC -G -compat=4... -lC example% CC -G -compat=5... -lCrun |
共有ライブラリが例外を使用している場合には、ライブラリが C++ 共有ライブラリに依存していないと、C プログラムが正しく動作しないことがあります。