C++教科書/標準ライブラリ編

編集

標準ライブラリとは

編集

C++標準ライブラリは、効率的なプログラミングに不可欠な包括的なツールセットです。コンテナ、アルゴリズム、入出力機能、文字列操作、並行処理など、幅広い機能を提供します。これらを活用することで、開発効率の向上、コードの品質改善、そしてクロスプラットフォームの互換性を実現できます。本書では、C++20/23の最新機能を含む標準ライブラリの各コンポーネントについて、実践的な例を交えながら解説します。

標準ライブラリの基本構造

編集

C++標準ライブラリは、以下のような機能群で構成されています:

コアライブラリ

編集

基本ユーティリティ

編集

データ構造とアルゴリズム

編集

特殊機能ライブラリ

編集

ヘッダーと名前空間の利用

編集

基本的な使用方法

編集

C++標準ライブラリのコンポーネントは、ヘッダーファイルとして提供され、std名前空間内に定義されています。利用するには、適切なヘッダーをインクルードし、std::修飾子を使用します:

#include <vector>
#include <string>

std::vector<int> numbers;
std::string text;

名前空間の best practices

編集

using宣言の適切な使用

編集
  • 推奨される方法
    特定の要素のみを使用する場合:
    using std::vector;
    using std::string;
    
    関数のスコープ内での限定的な使用:
    void process_data() {
        using std::cout;
        cout << "Processing..." << std::endl;
    }
    

using namespace std の問題点

編集

using namespace std;の使用は以下の理由で非推奨です:

  1. 名前の衝突:標準ライブラリの名前とユーザーコードの名前が予期せず衝突する可能性
  2. コードの明確性の低下:どの関数や型が標準ライブラリに属するのか不明確になる
  3. メンテナンス性への影響:将来的なコードの変更や拡張時に問題を引き起こす可能性
  4. 大規模プロジェクトでの管理困難:複数の名前空間が混在する際の依存関係の把握が困難

C++20以降の新機能

編集
  • モジュール:ヘッダーファイルの代替として、より効率的なモジュールシステムが導入(C++20)
  • レンジライブラリ:より直感的なコレクション操作
  • コルーチン:非同期プログラミングの新しいパラダイム
  • コンセプト:テンプレートの制約を明示的に表現

標準ライブラリヘッダー

編集
  • <algorithm> — 多様なアルゴリズムを提供するクラスと関数。(C++98)
  • <any> — 任意の型を保持できる型安全なコンテナ。(C++17)
  • <array> — 固定サイズの配列コンテナ。(C++11)
  • <atomic> — 原子操作。(C++11)
  • <barrier> — スレッドの同期のサポートするバリア。(C++20)
  • <bit> — ビット操作用のユーティリティ。(C++20)
  • <bitset> — 固定サイズのビット列コンテナ。(C++98)
  • <charconv> — 文字列と数値の変換。(C++17)
  • <chrono> — 時間の計測と操作のサポート。(C++11)
  • <codecvt> — 文字コード変換を行うファセット。(C++11、C++17で非推奨)
  • <compare> — 比較のサポート。(C++20)
  • <complex> — 複素数型のサポート。(C++98)
  • <concepts> — コンセプト定義。(C++20)
  • <condition_variable> — スレッド間の待機と通知のサポート。(C++11)
  • <coroutine> — コルーチンのサポート。(C++20)
  • <deque> — 両端キューコンテナ。(C++98)
  • <exception> — 例外処理のサポート。(C++98)
  • <execution> — 並列アルゴリズムの実行ポリシー。(C++17)
  • <expected> — エラーを返す可能性のある操作の結果。(C++23)
  • <filesystem> — ファイルシステム操作のサポート。(C++17)
  • <flat_map> — ソートされた連想コンテナ。(C++23)
  • <flat_set> — ソートされたセットコンテナ。(C++23)
  • <format> — 文字列のフォーマット機能。(C++20)
  • <forward_list> — 単方向リストコンテナ。(C++11)
  • <fstream> — ファイル入出力のサポート。(C++98)
  • <functional> — 関数オブジェクトとユーティリティ。(C++98)
  • <future> — 非同期操作の結果を取得。(C++11)
  • <generator> — ジェネレーターのサポート。(C++23)
  • <initializer_list> — 初期化リストのサポート。(C++11)
  • <iomanip> — 入出力ストリームの操作。(C++98)
  • <ios> — 基本的な入出力ストリームのクラス。(C++98)
  • <iosfwd> — 入出力ストリームクラスの前方宣言。(C++98)
  • <iostream> — 標準入出力ストリームオブジェクト。(C++98)
  • <istream> — 入力ストリームクラス。(C++98)
  • <iterator> — イテレータのユーティリティと型。(C++98)
  • <latch> — スレッド同期のためのラッチ。(C++20)
  • <limits> — 型の限界値情報を提供。(C++98)
  • <list> — 双方向リストコンテナ。(C++98)
  • <locale> — ロケールと国際化サポート。(C++98)
  • <map> — キーと値のペアを保持する連想コンテナ。(C++98)
  • <mdspan> — 多次元配列のビュー。(C++23)
  • <memory> — 動的メモリ管理とスマートポインタ。(C++98)
  • <memory_resource> — メモリリソースとポリシー。(C++17)
  • <mutex> — 相互排他制御のプリミティブ。(C++11)
  • <new> — 動的メモリ割り当ての管理。(C++98)
  • <numbers> — 数値定数の定義。(C++20)
  • <numeric> — 数値計算のユーティリティ。(C++98)
  • <optional> — オプショナル型。(C++17)
  • <ostream> — 出力ストリームクラス。(C++98)
  • <print> — 標準出力への出力のサポート。(C++23)
  • <queue> — FIFO(先入れ先出し)コンテナ。(C++98)
  • <random> — 乱数生成ライブラリ。(C++11)
  • <ranges> — 範囲ベースのアルゴリズム。(C++20)
  • <ratio> — コンパイル時の有理数演算。(C++11)
  • <regex> — 正規表現のサポート。(C++11)
  • <scoped_allocator> — スコープ付きアロケータのラッパー。(C++11)
  • <semaphore> — スレッド間の同期を制御。(C++20)
  • <set> — 集合コンテナ。(C++98)
  • <shared_mutex> — 共有と独占のロック制御。(C++14)
  • <source_location> — ソースコード位置情報。(C++20)
  • <span> — 連続メモリのビュー。(C++20)
  • <spanstream> — メモリバッファへのストリーム。(C++23)
  • <sstream> — 文字列ストリームクラス。(C++98)
  • <stack> — LIFO(後入れ先出し)コンテナ。(C++98)
  • <stacktrace> — スタックトレースのサポート。(C++23)
  • <stdexcept> — 標準的な例外クラス。(C++98)
  • <stdfloat> — 標準浮動小数点数。(C++23)
  • <stop_token> — 停止トークンのサポート。(C++20)
  • <streambuf> — ストリームバッファ。(C++98)
  • <string> — 文字列クラス。(C++98)
  • <string_view> — 文字列の読み取りビュー。(C++17)
  • <strstream> — 文字列バッファストリーム。(C++98、C++98で非推奨)
  • <syncstream> — 同期ストリーム出力。(C++20)
  • <system_error> — システムエラーの報告。(C++11)
  • <thread> — マルチスレッドのサポート。(C++11)
  • <tuple> — 異なる型のタプル。(C++11)
  • <type_traits> — 型特性の操作。(C++11)
  • <typeindex> — 型情報のインデックス。(C++11)
  • <typeinfo> — ランタイム型情報。(C++98)
  • <unordered_map> — ハッシュテーブル連想コンテナ。(C++11)
  • <unordered_set> — ハッシュテーブル集合コンテナ。(C++11)
  • <utility> — 汎用ユーティリティ。(C++98)
  • <valarray> — 数値配列クラス。(C++98)
  • <variant> — 複数の型を持つユニオン。(C++17)
  • <vector> — 動的配列コンテナ。(C++98)
  • <version> — バージョン情報。(C++20)

C言語互換ヘッダー

編集

C言語ヘッダーの先頭に c を補い末尾から .h を取り去る。

  • <cassert> — アサーションのサポート。(C++98)
  • <cctype> — 文字分類と変換。(C++98)
  • <cerrno> — エラーナンバー定義。(C++98)
  • <cfenv> — 浮動小数点環境の制御。(C++11)
  • <cfloat> — 浮動小数点数の特性。(C++98)
  • <cinttypes> — 整数型のフォーマット変換。(C++11)
  • <climits> — 整数型の限界値。(C++98)
  • <clocale> — ロケールの設定と取得。(C++98)
  • <cmath> — 数学関数ライブラリ。(C++98)
  • <csetjmp> — 非局所ジャンプのサポート。(C++98)
  • <csignal> — シグナル処理のサポート。(C++98)
  • <cstdarg> — 可変引数リストの操作。(C++98)
  • <cstddef> — 標準型とマクロ。(C++98)
  • <cstdint> — 固定幅整数型。(C++11)
  • <cstdio> — 標準入出力関数。(C++98)
  • <cstdlib> — 標準ライブラリのユーティリティ。(C++98)
  • <cstring> — 文字列操作関数。(C++98)
  • <ctime> — 時間処理関数。(C++98)
  • <cuchar> — Unicode文字操作関数。(C++11)
  • <cwchar> — ワイド文字操作関数。(C++98)
  • <cwctype> — ワイド文字分類と変換。(C++98)

C言語ヘッダー

編集

全て(C++98)

標準ライブラリヘッダー分類表
ヘッダー 分類 初出 説明
<concepts> — コンセプト C++20 コンセプト基本ライブラリ
<coroutine> — コルーチン C++20 コルーチンサポートライブラリ
<any> — ユーティリティ C++17 std::anyクラス
<bitset> — ユーティリティ - std::bitsetクラステンプレート
<chrono> — ユーティリティ C++11 C++時間ユーティリティ
<compare> — ユーティリティ C++20 3方向比較演算子サポート
<csetjmp> — ユーティリティ - 実行コンテキストを保存/ジャンプするマクロ(と関数)
<csignal> — ユーティリティ - シグナル管理の関数とマクロ定数
<cstdarg> — ユーティリティ - 可変長引数リストの処理
<cstddef> — ユーティリティ - 標準マクロとtypedef
<cstdlib> — ユーティリティ - 一般的なユーティリティ:プログラム制御、動的メモリ割り当て、乱数、ソートと検索
<ctime> — ユーティリティ - C形式の時刻/日付ユーティリティ
<debugging> — ユーティリティ C++26 デバッグライブラリ
<expected> — ユーティリティ C++23 std::expectedクラステンプレート
<functional> — ユーティリティ - 関数オブジェクト、関数呼び出し、バインド操作、参照ラッパー
<initializer_list> — ユーティリティ C++11 std::initializer_listクラステンプレート
<optional> — ユーティリティ C++17 std::optionalクラステンプレート
<source_location> — ユーティリティ C++20 ソースコード位置を取得する手段を提供
<tuple> — ユーティリティ C++11 std::tupleクラステンプレート
<type_traits> — ユーティリティ C++11 コンパイル時型情報
<typeindex> — ユーティリティ C++11 std::type_index
<typeinfo> — ユーティリティ - 実行時型情報ユーティリティ
<utility> — ユーティリティ - 様々なユーティリティコンポーネント
<variant> — ユーティリティ C++17 std::variantクラステンプレート
<version> — ユーティリティ C++20 実装依存のライブラリ情報を提供
<memory> — 動的メモリ管理 - 高レベルメモリ管理ユーティリティ
<memory_resource> — 動的メモリ管理 C++17 多相的アロケータとメモリリソース
<new> — 動的メモリ管理 - 低レベルメモリ管理ユーティリティ
<scoped_allocator> — 動的メモリ管理 C++11 ネストされたアロケータクラス
<cfloat> — 数値限界 - 浮動小数点型の限界値
<cinttypes> — 数値限界 C++11 書式マクロ、intmax_tuintmax_t、数学と変換
<climits> — 数値限界 - 整数型の限界値
<cstdint> — 数値限界 C++11 固定幅整数型と他の型の限界値
<limits> — 数値限界 - 算術型のプロパティを問い合わせる統一された方法
<stdfloat> — 数値限界 C++23 オプションの拡張浮動小数点型
<cassert> — エラー処理 - ゼロと比較し、条件付きでマクロを定義
<cerrno> — エラー処理 - 最後のエラー番号を含むマクロ
<exception> — エラー処理 - 例外処理ユーティリティ
<stacktrace> — エラー処理 C++23 スタックトレースライブラリ
<stdexcept> — エラー処理 - 標準例外オブジェクト
<system_error> — エラー処理 C++11 std::error_codeを定義(プラットフォーム依存のエラーコード)
<cctype> — 文字列 - ナロー文字のカテゴリを判別する関数
<charconv> — 文字列 C++17 std::to_charsstd::from_chars
<cstring> — 文字列 - 様々なナロー文字列処理関数
<cuchar> — 文字列 C++11 C形式のUnicode文字変換関数
<cwchar> — 文字列 - 様々なワイド/マルチバイト文字列処理関数
<cwctype> — 文字列 - ワイド文字のカテゴリを判別する関数
<format> — 文字列 C++20 書式化ライブラリ(std::formatを含む)
<string> — 文字列 - std::basic_stringクラステンプレート
<string_view> — 文字列 C++17 std::basic_string_viewクラステンプレート
<array> — コンテナ C++11 std::arrayコンテナ
<deque> — コンテナ - std::dequeコンテナ
<flat_map> — コンテナ C++23 std::flat_mapstd::flat_multimapコンテナアダプター
<flat_set> — コンテナ C++23 std::flat_setstd::flat_multisetコンテナアダプター
<forward_list> — コンテナ C++11 std::forward_listコンテナ
<list> — コンテナ - std::listコンテナ
<map> — コンテナ - std::mapstd::multimapの連想コンテナ
<mdspan> — コンテナ C++23 std::mdspanビュー
<queue> — コンテナ - std::queuestd::priority_queueのコンテナアダプター
<set> — コンテナ - std::setstd::multisetの連想コンテナ
<span> — コンテナ C++20 std::spanビュー
<stack> — コンテナ - std::stackコンテナアダプター
<unordered_map> — コンテナ C++11 std::unordered_mapstd::unordered_multimapの非順序連想コンテナ
<unordered_set> — コンテナ C++11 std::unordered_setstd::unordered_multisetの非順序連想コンテナ
<vector> — コンテナ - std::vectorコンテナ
<iterator> — イテレータ - 範囲イテレータ
<generator> — 範囲 C++23 std::generatorクラステンプレート
<ranges> — 範囲 C++20 範囲アクセス、プリミティブ、要件、ユーティリティ、アダプター
<algorithm> — アルゴリズム - 範囲に作用するアルゴリズム
<execution> — アルゴリズム C++17 アルゴリズムの並列バージョンに対する既定の実行ポリシー
<bit> — 数値 C++20 ビット操作関数
<cfenv> — 数値 C++11 浮動小数点環境アクセス関数
<cmath> — 数値 - 共通の数学関数
<complex> — 数値 - 複素数型
<linalg> — 数値 C++26 基本的な線形代数アルゴリズム
<numbers> — 数値 C++20 数学定数
<numeric> — 数値 - 範囲内の値に対する数値演算
<random> — 数値 C++11 乱数生成器と分布
<ratio> — 数値 C++11 コンパイル時有理数演算
<valarray> — 数値 - 値の配列を表現し操作するためのクラス
<clocale> — 地域化 - C言語の地域化ユーティリティ
<codecvt> — 地域化 C++11 Unicode変換機能 (C++17で非推奨、C++26で削除)
<locale> — 地域化 - 地域化ユーティリティ
<text_encoding> — 地域化 C++26 テキストエンコーディングの識別
<cstdio> — 入出力 - C形式の入出力関数
<fstream> — 入出力 - std::basic_fstreamstd::basic_ifstreamstd::basic_ofstreamクラステンプレートといくつかのtypedef
<iomanip> — 入出力 - 入出力のフォーマットを制御するヘルパー関数
<ios> — 入出力 - std::ios_baseクラス、std::basic_iosクラステンプレート、いくつかのtypedef
<iosfwd> — 入出力 - 入出力ライブラリのすべてのクラスの前方宣言
<iostream> — 入出力 - 様々な標準ストリームオブジェクト
<istream> — 入出力 - std::basic_istreamクラステンプレート、いくつかのtypedef
<ostream> — 入出力 - std::basic_ostreamstd::basic_iostreamクラステンプレート、いくつかのtypedef
<print> — 入出力 C++23 書式付き出力ライブラリ(std::printを含む)
<spanstream> — 入出力 C++23 std::basic_spanstreamstd::basic_ispanstreamstd::basic_ospanstreamクラステンプレート、typedef
<sstream> — 入出力 - std::basic_stringstreamstd::basic_istringstreamstd::basic_ostringstreamクラステンプレート、いくつかのtypedef
<streambuf> — 入出力 - std::basic_streambufクラステンプレート
<syncstream> — 入出力 C++20 std::basic_osyncstreamstd::basic_syncbuf、typedef
<filesystem> — ファイルシステム C++17 std::pathクラスとサポート関数
<regex> — 正規表現 C++11 正規表現処理のサポートするクラス、アルゴリズム、イテレータ
<atomic> — 原子操作 C++11 原子操作ライブラリ
<barrier> — スレッドサポート C++20 バリア
<condition_variable> — スレッドサポート C++11 スレッド待機条件
<future> — スレッドサポート C++11 非同期コンピューティングのプリミティブ
<hazard_pointer> — スレッドサポート C++26 ハザードポインター
<latch> — スレッドサポート C++20 ラッチ
<mutex> — スレッドサポート C++11 相互排除プリミティブ
<rcu> — スレッドサポート C++26 Read-Copy Update メカニズム
<semaphore> — スレッドサポート C++20 セマフォ
<shared_mutex> — スレッドサポート C++14
<stop_token> — スレッドサポート C++20 std::jthreadの停止トークン
<thread> — スレッドサポート C++11 std::threadクラスとサポート関数
<assert.h> — C互換 -- <cassert>と同様の振る舞い
<ctype.h> — C互換 -- <cctype>からすべての名前が大域名前空間に配置されているかのように振る舞う
<errno.h> — C互換 -- <cerrno>と同様の振る舞い
<fenv.h> — C互換 -- <cfenv>からすべての名前が大域名前空間に配置されているかのように振る舞う
<float.h> — C互換 -- <cfloat>と同様の振る舞い
<inttypes.h> — C互換 -- <cinttypes>からすべての名前が大域名前空間に配置されているかのように振る舞う
<limits.h> — C互換 -- <climits>と同様の振る舞い
<locale.h> — C互換 -- <clocale>からすべての名前が大域名前空間に配置されているかのように振る舞う
<math.h> — C互換 -- <cmath>からすべての名前(数学特殊関数の名前を除く)が大域名前空間に配置されているかのように振る舞う
<setjmp.h> — C互換 -- <csetjmp>からすべての名前が大域名前空間に配置されているかのように振る舞う
<signal.h> — C互換 -- <csignal>からすべての名前が大域名前空間に配置されているかのように振る舞う
<stdarg.h> — C互換 -- <cstdarg>からすべての名前が大域名前空間に配置されているかのように振る舞う
<stddef.h> — C互換 -- <cstddef>からstd::byteと関連する関数の名前を除きすべての名前が大域名前空間に配置されているかのように振る舞う
<stdint.h> — C互換 -- <cstdint>からすべての名前が大域名前空間に配置されているかのように振る舞う
<stdio.h> — C互換 -- <cstdio>からすべての名前が大域名前空間に配置されているかのように振る舞う
<stdlib.h> — C互換 -- <cstdlib>からすべての名前が大域名前空間に配置されているかのように振る舞う
<string.h> — C互換 -- <cstring>からすべての名前が大域名前空間に配置されているかのように振る舞う
<time.h> — C互換 -- <ctime>からすべての名前が大域名前空間に配置されているかのように振る舞う
<uchar.h> — C互換 -- <cuchar>からすべての名前が大域名前空間に配置されているかのように振る舞う
<wchar.h> — C互換 -- <cwchar>からすべての名前が大域名前空間に配置されているかのように振る舞う
<wctype.h> — C互換 -- <cwctype>からすべての名前が大域名前空間に配置されているかのように振る舞う
<stdatomic.h> — 特殊C互換 -- _Atomicマクロを定義し、C標準ライブラリから対応する コンポーネントを提供する

コンテナ

編集

コンテナは、データを格納するためのオブジェクトであり、C++の標準ライブラリではさまざまな種類のコンテナが提供されています。それぞれのコンテナは、異なる目的や使用方法に適しています。以下では、主要なコンテナについて詳しく説明します。

コンテナの種類

編集

C++ 標準ライブラリは、以下の主要なコンテナを提供しています。

  • 配列 (std::array): 固定長の要素の集合を表す。ランダムアクセスが高速だが、サイズ変更ができない。
  • ベクター (std::vector): 動的な要素の集合を表す。要素の挿入・削除が効率的かつ、ランダムアクセスも高速。
  • リスト (std::list): 双方向連結リストを表す。要素の挿入・削除が効率的だが、ランダムアクセスは遅い。
  • スタック (std::stack): LIFO (Last In First Out) 構造を表す。プッシュとポップの操作を提供。
  • キュー (std::queue): FIFO (First In First Out) 構造を表す。エンキューとデキューの操作を提供。
  • デック (std::deque): 両端キューを表す。先頭と末尾の両方から要素の挿入・削除が可能。
  • セット (std::set): 重複のない要素の集合を表す。要素は昇順にソート済み。
  • マップ (std::map): キーと値のペアの集合を表す。キーに基づいて値を検索できる。
  • アンオーダードセット (std::unordered_set): ハッシュテーブルを用いて要素を格納する。重複のない要素の集合を表す。
  • アンオーダードマップ (std::unordered_map): ハッシュテーブルを用いてキーと値のペアを格納する。

各コンテナの詳細

編集

それぞれのコンテナについて、以下に詳細を説明します。

配列 (std::array)

編集
auto my_array = std::array{2, 3, 5, 7, 11};
  • 要素の数と型は固定で、コンパイル時に決定される。
  • ランダムアクセスが高速 (O(1))。
  • 要素の挿入・削除はできない。
  • メモリ消費量が事前に予測可能。
  • 領域はスタックに確保される。
  • コア言語の配列とは異なり、イテレータやアルゴリズムを適用できる。

ベクター (std::vector)

編集
auto my_vector = std::vector{2, 3, 5, 7, 11};
my_vector.push_back(13);
my_vector.push_back(17);
my_vector.push_back(19);
  • 要素数は可変で、実行時に動的に変更できる。
  • ランダムアクセスが高速 (O(1))。
  • 要素の挿入・削除が効率的 (挿入: O(1) or O(n)、削除: O(1) or O(n))。
  • メモリ消費量は動的に変化する。
  • 領域はヒープに確保される。
  • スコープを離れる自動的に領域開放される。

リスト (std::list)

編集
auto my_list = std::list{2, 3, 5, 7, 11};
my_list.push_back(13);
my_list.push_back(17);
my_list.push_back(19);
  • 要素は双方向連結リストで管理される。
  • ランダムアクセスは遅い (O(n))。
  • 要素の挿入・削除が効率的 (O(1))。
  • 隣接要素へのアクセスや挿入・削除に適している。

スタック (std::stack)

編集
auto my_stack = std::stack{2, 3, 5, 7, 11};
my_stack.push(13);
my_stack.push(17);
my_stack.push(19);
int peek = my_stack.top();
int top = my_stack.pop();
  • LIFO 構造を実装。
  • プッシュとポップの操作を提供。
  • ネストされたスコープの管理などに利用される。

キュー (std::queue)

編集
std::queue<int> my_queue;
my_queue.push(1);
my_queue.push(2);
my_queue.push(3);
int front = my_queue.front();
my_queue.pop();
  • FIFO 構造を実装。
  • エンキューとデキューの操作を提供。
  • タスクのキューイングなどに利用される。

デック (std::deque)

編集
std::deque<int> my_deque;
my_deque.push_back(1);
my_deque.push_front(2);
my_deque.push_back(3);
int front = my_deque.front();
int back = my_deque.back();
my_deque.pop_front();
my_deque.pop_back();
  • 両端キューとして動作
  • 先頭と末尾の両方から要素の挿入・削除が可能。
  • ランダムアクセスも可能だが、std::vectorほど高速ではない (O(log n))。
  • std::vectorstd::listの両方の特性を持つ。

セット (std::set)

編集
std::set<int> my_set;
my_set.insert(1);
my_set.insert(2);
my_set.insert(3);
bool found = my_set.find(2) != my_set.end();
  • 重複のない要素の集合を表す。
  • 要素は昇順にソート済み。
  • 探索、挿入、削除の操作が高速 (O(log n))。
  • 順序を保持する必要がある集合の操作に適している。

マップ (std::map)

編集
std::map<std::string, int> my_map;
my_map["key1"] = 1;
my_map["key2"] = 2;
my_map["key3"] = 3;
int value = my_map["key2"];
  • キーと値のペアの集合を表す。
  • キーに基づいて値を効率的に検索できる (O(log n))。
  • 挿入、削除、検索の操作が高速 (O(log n))。
  • キーと値の対応関係を保持する必要がある場合に適している。

アンオーダードセット (std::unordered_set)

編集
std::unordered_set<int> my_set;
my_set.insert(1);
my_set.insert(2);
my_set.insert(3);
bool found = my_set.find(2) != my_set.end();
  • ハッシュテーブルを用いて要素を格納。
  • 重複のない要素の集合を表す。
  • 探索、挿入、削除の操作が非常に高速 (平均 O(1))。
  • 順序を保持する必要がない集合の操作に適している。

アンオーダードマップ (std::unordered_map)

編集
std::unordered_map<std::string, int> my_map;
my_map["key1"] = 1;
my_map["key2"] = 2;
my_map["key3"] = 3;
int value = my_map["key2"];
  • ハッシュテーブルを用いてキーと値のペアを格納。
  • キーに基づいて値を非常に効率的に検索できる (平均 O(1))。
  • 挿入、削除、検索の操作が非常に高速 (平均 O(1))。
  • キーと値の対応関係を保持する必要がある場合に適しているが、順序は保持されない。

コンテナの選択

編集

適切なコンテナを選択することは、プログラムのパフォーマンスと効率に大きく影響します。

  • コア言語の配列と同様に高速かつスタックにインスタンスを起きたく、イテレータやアルゴリズムを使いたい場合は std::arrayを選択します。
  • 要素へのランダムアクセスが必要な場合は、std::vectorまたはstd::dequeを選択します。
  • 要素の挿入・削除が頻繁に行われる場合は、std::vectorまたはstd::listを選択します。
  • 順序を保持する必要のない集合を扱う場合は、std::unordered_setまたはstd::unordered_mapを選択します。
  • キーと値のペアを扱う場合は、std::unordered_mapまたはstd::unordered_mapを選択します。

各コンテナの特性をよく理解し、状況に応じて適切なコンテナを選択することが重要です。

まとめ

C++ 標準ライブラリは、さまざまなコンテナを提供しており、それぞれ異なる特徴と利点を持っています。プログラムの目的に合ったコンテナを選択することで、効率的で高速なコードを書くことができます。

アルゴリズム

編集

アルゴリズムとは、問題を解決するための手順の明確な定義です。一般的に、以下の要素で構成されます。

  • 入力: アルゴリズムが処理するデータ
  • 処理: 入力データに対して行う操作
  • 出力: アルゴリズムによって生成される結果

C++標準ライブラリでは、様々な種類のアルゴリズムが提供されており、それぞれ異なる入力、処理、出力を持つように設計されています。

標準ライブラリにおけるアルゴリズム

編集

C++標準ライブラリのアルゴリズムは、ヘッダー <algorithm> に定義されています。このヘッダーには、以下の機能が含まれます。

分類 代表的なアルゴリズム
検索 std::find, std::search, std::count, std::count_if
ソート std::sort, std::stable_sort, std::partial_sort, std::nth_element
範囲 std::copy, std::copy_if, std::swap, std::fill, std::fill_n, std::replace, std::replace_if, std::remove, std::remove_if
変換 std::transform, std::for_each, std::generate, std::generate_n
その他 std::max, std::min, std::minmax, std::swap_ranges, std::set_difference, std::set_intersection, std::set_union, std::adjacent_find, std::mismatch, std::copy_backward, std::move, std::move_backward, std::rotate, std::rotate_copy, std::shuffle, std::random_shuffle, std::partition, std::partition_point, std::stable_partition, std::is_sorted, std::is_partially_sorted, std::unique, std::unique_copy, std::count_elements, std::upper_bound, std::lower_bound, std::binary_search, std::merge, std::inplace_merge, std::set_union_of_ranges, std::lexicographical_compare, std::includes, std::adjacent_difference, std::search_n, std::copy_n, std::iota, std::iota_n, std::for_each_n, std::generate_n, std::gather, std::scatter, std::reduce, std::reduce_right, std::adjacent_reduce, std::accumulate, std::accumulate_right, std::transform_reduce, std::transform_reduce_right, std::max_element, std::min_element, std::max_element_n, std::min_element_n, std::minmax_element, std::minmax_element_n, std::any_of, std::all_of, std::none_of, std::count_if_n, std::find_if, std::find_if_n, std::find_first_of, std::find_first_of_n, std::any_of_n, std::all_of_n, std::none_of_n

ソート (sort)

編集

ソートは、データの要素を昇順または降順に整列するアルゴリズムです。C++の標準ライブラリでは、std::sort関数が提供されており、クイックソートやヒープソートなどの高速なソートアルゴリズムが実装されています。

検索 (search)

編集

検索は、与えられたデータから特定の要素を見つけるアルゴリズムです。C++の標準ライブラリでは、std::find関数が提供されており、線形検索やバイナリ検索などの効率的な検索アルゴリズムが実装されています。

二分探索 (binary_search)

編集

二分探索は、ソート済みのデータから特定の要素を効率的に見つけるアルゴリズムです。C++の標準ライブラリでは、std::binary_search関数が提供されており、対象の要素が存在するかどうかを判定することができます。

変更 (modify)

編集

変更は、データの要素を変更する操作を行うアルゴリズムです。C++の標準ライブラリでは、std::transform関数が提供されており、与えられた操作を各要素に適用することができます。

パーミュテーション (permutation)

編集

パーミュテーションは、与えられた要素の順列を生成するアルゴリズムです。C++の標準ライブラリでは、std::next_permutation関数が提供されており、要素の順列を効率的に生成することができます。

集計 (accumulate)

編集

集計は、与えられたデータの要素を合計する操作を行うアルゴリズムです。C++の標準ライブラリでは、std::accumulate関数が提供されており、要素の合計を計算することができます。

#include <iostream>
#include <numeric>  // std::accumulate
#include <vector>

auto main() -> int {
    auto numbers = std::vector{1, 2, 3, 4, 5};
    auto const sum = std::accumulate(numbers.begin(), numbers.end(), 0);

    std::cout << "Sum: " << sum << std::endl;

    return 0;
}

順列生成 (next_permutation)

編集

順列生成は、与えられた要素の全ての順列を生成するアルゴリズムです。C++の標準ライブラリでは、std::next_permutation関数が提供されており、与えられた要素の順列を効率的に生成することができます。

ヒープ操作 (heap)

編集

ヒープ操作は、ヒープデータ構造を操作するアルゴリズムです。C++の標準ライブラリでは、std::make_heapstd::push_heapstd::pop_heapなどの関数が提供されており、ヒープを構築したり、要素を追加・削除したりすることができます。

イテレータとアダプタ

編集

イテレータ(iterator)は、コンテナの要素を参照し、反復処理を実現するためのオブジェクトです。標準ライブラリでは様々なイテレータが定義されており、それらを使うことで柔軟でパフォーマンスの良いアルゴリズムを記述できます。

代表的なイテレータには以下のようなものがあります。

入力イテレータ(input iterator)
要素の読み取り専用
出力イテレータ(output iterator)
要素の書き込み専用
前方イテレータ(forward iterator)
単方向の反復が可能
双方向イテレータ(bidirectional iterator)
前方と逆方向の反復が可能
ランダムアクセスイテレータ(random access iterator)
任意のインデックスにアクセス可能
auto v = std::vector{1, 2, 3, 4, 5};
for(std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
    std::cout << *it << " "; // 出力: 1 2 3 4 5
}

アダプタ(adapter)は、既存のコンテナやイテレータから新しいビューを生成するための仕組みです。アダプタを使うことで、コピーを作らずに既存のコンテナの動作をカスタマイズできます。

よく使われるシーケンスアダプタには以下のようなものがあります。

std
:reverse_iterator : 逆向きのイテレータを生成
std
:move_iterator : ムーブ操作ができるイテレータを生成
std
:inserter : 出力イテレータをコンテナに挿入操作するアダプタ
auto lst = std::list{1, 2, 3, 4, 5};
std::vector<int> vec(lst.size());
std::copy(lst.begin(), lst.end(), std::back_inserter(vec));
// vecには{1, 2, 3, 4, 5}が代入される

このように、イテレータとアダプタを適切に組み合わせることで、C++の標準ライブラリを活用した効率的で柔軟なコーディングが可能になります。

文字列、文字列操作と正規表現

編集

文字列(std::string, std::wstring)

編集

C++ではstd::stringクラスが文字列を表すために使われます。このクラスは様々なコンストラクタと、文字列の連結、検索、置換などの操作を行うメンバー関数を提供しています。

std::string s1 = "Hello"; // コンストラクタ
std::string s2 = s1 + " World"; // 連結
// 部分文字列の検索
if (s2.find("llo") != std::string::npos) {
    /* ... */
} 
s2.replace(6, 5, "Universe"); // 置換

std::wstringはワイド文字列を扱うためのクラスで、多言語対応アプリケーションで使われます。

文字列ストリーム(std::stringstream)

編集

std::stringstreamクラスを使うと、stringオブジェクトと入出力ストリームの間で簡単に変換できます。

std::stringstream ss;
ss << "Value = " << 3.14; 
std::string s = ss.str(); // s == "Value = 3.14"

文字列リテラル(std::string_view, std::u8string_view)

編集

C++17から導入されたstd::string_viewはstring_literalを所有せずにビューとして参照するためのクラスです。メモリ消費を抑えられる一方で、nullターミネートを要求するので注意が必要です。

正規表現(std::regex, std::smatch, std::regex_replace, など)

編集

C++11から正規表現をサポートするライブラリが導入されました。std::regexを使って正規表現オブジェクトを作成し、std::smatchでマッチング結果を扱えます。また、std::regex_replaceで置換も行えます。

std::regex re("\\d+"); // 正規表現オブジェクト
std::string s = "Sample 123 456";
std::smatch m;
if (std::regex_search(s, m, re)) { // マッチング
    // m[0]にマッチした文字列が入る
}
std::string result = std::regex_replace(s, re, "NUM"); // Sample NUM NUM

ECMAScriptの正規表現構文をサポートしており、文字列操作を行う上で非常に強力なツールとなっています。

入出力

編集

入出力操作は、プログラミングにおいて非常に重要な要素です。C++の標準ライブラリでは、さまざまな形式のデータの読み書きを行うための豊富な機能が提供されています。以下では、主要な入出力について説明します。

標準入出力 (iostream)

編集

標準入出力は、プログラムとユーザーまたは他のプログラムの間でデータをやり取りするための機能です。C++の標準ライブラリでは、std::cinstd::coutというストリームオブジェクトを使用して標準入力と標準出力を操作することができます。これらのストリームを使用することで、データの読み取りや表示を簡単に行うことができます。

ファイル入出力 (fstream)

編集

ファイル入出力は、ファイルとプログラムの間でデータを読み書きするための機能です。C++の標準ライブラリでは、ファイル入出力ストリームを操作するためのstd::ifstreamstd::ofstreamクラスが提供されています。これらのクラスを使用することで、ファイルからデータを読み取ったり、ファイルにデータを書き込んだりすることができます。

【廃止】文字コード変換 (std::codecvt)

編集

std::codecvtクラスは、C++17で非推奨となり、C++26で削除されることが決定されました。この変更の背景には、この機能がUnicodeの現在の標準をサポートしておらず、古いUCS-2エンコーディングのみをサポートしていたことがあります。

代替手段としては、次のようなオプションが考えられます。

std::wstring_convert
C++11で導入されたstd::wstring_convertクラスを使用します。このクラスは、広くサポートされているUTF-8、UTF-16、UTF-32エンコーディングをサポートしています。
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
std::u32string u32 = conv.from_bytes(u8"Hello");
std::string bytes = conv.to_bytes(u32);
ライブラリの使用
外部ライブラリを使用することができます。例えば、ICUライブラリ(International Components for Unicode)は、Unicode文字列の変換や正規化など、幅広い機能を提供しています。
独自の実装
特定のニーズに合わせて、独自の文字列変換ロジックを実装することもできます。ただし、Unicodeの扱いは複雑であるため、既存のライブラリを利用することをお勧めします。

また、文字列リテラルの導入により、ソースコード中に直接UTF-8やUTF-16、UTF-32の文字列を書くことができるようになりました。

auto u8_str = u8"UTF-8 文字列";
auto u_str =  U"UTF-16 文字列";
auto U8_str = u8"UTF-8 文字列";
auto U_str =  U"UTF-16 文字列";

さらに、C++17からはstd::bytestd::byte_traitsといった、バイトベースの操作を行うための機能が追加されています。文字変換の際にこれらを活用することで、std::codecvtに頼らずに済むケースが増えました。

std::codecvtクラスの廃止は、C++がUnicodeの最新の標準に対応するための変更です。代替手段を検討することで、アプリケーションのUnicode対応を改善できるでしょう。

ファイルシステム (filesystem)

編集

ファイルシステムは、ファイルやディレクトリの操作を行うための機能です。C++17からは、std::filesystemライブラリが標準化され、ファイルやディレクトリの操作を行うためのさまざまなクラスや関数が提供されています。これにより、プログラムがファイルシステムを操作する際に、簡単にファイルやディレクトリを作成、削除、移動、検索することができます。

例外処理

編集

例外処理は、プログラム実行中に予期しないエラーが発生した場合に、適切に対処するための仕組みです。C++の標準ライブラリでは、例外処理をサポートするためのさまざまな機能が提供されています。以下では、主要な例外処理について説明します。

例外の基本 (exception basics)

編集

例外は、プログラム実行中に予期しないエラーが発生した場合に発生します。例外は、プログラムの実行を中断し、エラーが発生した場所から例外処理のコードに制御を移します。例外処理は、例外が発生した際に適切な処理を行うための仕組みです。

例外の送出と捕捉 (throwing and catching exceptions)

編集

例外の送出は、予期しないエラーが発生した場合に、そのエラーを通知するために使用されます。C++では、throwキーワードを使用して例外を明示的に送出することができます。一方、例外の捕捉は、送出された例外を処理するための仕組みです。tryブロック内で例外が送出される可能性があるコードを記述し、その後にcatchブロックを使用して例外を捕捉し、適切な処理を行うことができます。

標準例外クラス (standard exception classes)

編集

C++の標準ライブラリでは、さまざまな種類の例外を表すための標準例外クラスが提供されています。これらのクラスは、std::exceptionクラスを基底クラスとしており、異なる種類のエラーを表すために派生クラスとして使用されます。一般的な標準例外クラスには、std::runtime_errorstd::logic_errorstd::invalid_argumentなどがあります。これらのクラスは、特定の種類のエラーを表すために使用され、例外が送出された際にプログラムが適切に処理できるようにします。

その他の重要な機能

編集

C++の標準ライブラリには、さまざまな追加機能が提供されています。以下では、その他の重要な機能について説明します。

時間と日付 (date and time)

編集

時間と日付の操作は、多くのアプリケーションで重要な要素です。C++の標準ライブラリでは、時間や日付を表すためのstd::chronoライブラリが提供されています。このライブラリを使用することで、日付の取得、計算、比較などの操作を行うことができます。また、時間の測定や待機などの機能も提供されています。

メモリ管理 (memory management)

編集

メモリ管理は、プログラムが動作するために必要なメモリの割り当てと解放を行う重要な要素です。C++の標準ライブラリでは、メモリ管理を行うための機能が提供されており、std::allocatorクラスやstd::shared_ptrstd::unique_ptrなどのスマートポインタが使用されます。これらの機能を使用することで、メモリリークや二重解放などの問題を回避することができます。

スレッドと並行性 (threads and concurrency)

編集

スレッドと並行性は、現代のプログラミングにおいて重要な要素です。C++の標準ライブラリでは、マルチスレッドプログラミングをサポートするための機能が提供されています。std::threadクラスやstd::mutexstd::condition_variableなどのクラスを使用することで、スレッド間の同期や通信を行うことができます。また、C++11以降では、スレッドプールや非同期タスクなどの機能も提供されています。

数学関数 (math functions)

編集

数学関数は、科学技術計算やグラフィックスプログラミングなどの領域で広く使用されます。C++の標準ライブラリでは、数学関数を提供するための数多くの関数が提供されています。これには、三角関数、指数関数、対数関数、乱数生成などが含まれます。これらの関数を使用することで、数学的な計算を効率的に行うことができます。

ランダム数生成 (random number generation)

編集

ランダム数生成は、シミュレーションやゲームなどの分野で広く使用されます。C++の標準ライブラリでは、ランダム数を生成するためのさまざまな機能が提供されています。これには、線形合同法やメルセンヌ・ツイスターなどのアルゴリズムを使用した乱数生成器が含まれます。また、乱数生成器を使用して特定の範囲の乱数を生成する機能も提供されています。

標準ライブラリの最適化

編集

標準ライブラリの最適化は、プログラムのパフォーマンスを向上させるために重要なステップです。以下では、標準ライブラリを使用する際の最適化について説明します。

使用時の注意点

編集

標準ライブラリを使用する際に注意するべきポイントがいくつかあります。まず、適切なコンテナやアルゴリズムを選択することが重要です。特定の操作に適したコンテナやアルゴリズムを選択することで、効率的なプログラムを作成することができます。また、不要なコピーの回避やムーブセマンティクスの活用など、効率的なプログラミング手法を採用することも重要です。

さらに、標準ライブラリの使用に伴うオーバーヘッドにも注意が必要です。標準ライブラリは一般的に汎用的な実装を提供していますが、特定の状況においてはカスタム実装がより効率的な場合があります。プログラムの特性や要件に応じて、標準ライブラリの使用を最適化することが重要です。

パフォーマンスの向上方法

編集

標準ライブラリのパフォーマンスを向上させるためには、いくつかの方法があります。まず、最適化フラグを使用してコンパイラに最適化を指示することが重要です。最適化フラグを適切に設定することで、コンパイル時に効率的なコードが生成される可能性が高まります。

また、コンテナやアルゴリズムの選択によってもパフォーマンスを向上させることができます。例えば、ベクターやアレイなどの連続したメモリ配置を持つコンテナは、ランダムアクセスやイテレーションが高速に行えるため、大量のデータを効率的に処理する際に適しています。さらに、アルゴリズムの選択によってもパフォーマンスを向上させることができます。例えば、ソートアルゴリズムや探索アルゴリズムの選択によって、処理速度を向上させることができます。

さらに、並列処理やメモリ管理の最適化など、他の最適化手法も検討する価値があります。並列処理を使用することで、複数のスレッドを使用して処理を並列化することができ、処理速度を向上させることができます。また、メモリ管理の最適化を行うことで、不要なメモリの割り当てや解放を減らすことができ、プログラムのパフォーマンスを向上させることができます。


外部リンク

編集
 
Wikipedia
ウィキペディア標準C++ライブラリの記事があります。