C++/標準ライブラリ
C++教科書/標準ライブラリ編[編集]
標準ライブラリとは[編集]
C++標準ライブラリは、プログラミングの基本機能を提供する膨大なコレクションです。これには、コンテナ、アルゴリズム、入出力、文字列操作、並行性サポートなどが含まれます。標準ライブラリを利用することで、プログラムの開発効率が向上し、コードの可読性や保守性が高まります。本書では、標準ライブラリの各部分を詳しく説明し、その利用方法を具体的な例を通じて紹介します。
標準ライブラリの基本構造[編集]
C++標準ライブラリは、以下のように構成されています。
- 言語サポートライブラリ
- コンセプトライブラリ
- 診断ライブラリ
- メモリ管理ライブラリ
- メタプログラミングライブラリ
- 一般ユーティリティライブラリ
- 文字列ライブラリ
- コンテナライブラリ
- イテレータライブラリ
- レンジライブラリ
- アルゴリズムライブラリ
- 数値ライブラリ
- 時間ライブラリ
- ローカライゼーションライブラリ
- 入出力ライブラリ
- 正規表現ライブラリ
- 並行性サポートライブラリ
各ライブラリは、それぞれ特定の機能を提供し、C++プログラムを強力にサポートします。
ヘッダーと名前空間の概要[編集]
C++の標準ライブラリは、ヘッダーとして提供されます。ヘッダーには、さまざまなクラスや関数の宣言、定数、型の定義などが含まれます。これにより、プログラマは必要な機能を簡単にインクルードして利用することができます。
また、標準ライブラリのコンポーネントは、名前空間にまとめられています。これにより、同じ名前を持つ異なるライブラリのコンポーネントが衝突することを防ぎ、プログラムの整合性を保つことができます。例えば、std::vector
やstd::string
など、標準ライブラリのコンポーネントは、すべてstd
という名前空間に含まれています。
using namespace std; は非推奨[編集]
using namespace std;
は非推奨です。理由は以下の通りです:
- 名前の衝突のリスク:標準ライブラリの名前とユーザー定義の名前が衝突する可能性があります。
- 可読性の低下:コードを読むときに、標準ライブラリの名前かユーザー定義の名前かが判別しにくくなります。
- 大規模プロジェクトでの管理の難しさ:異なる名前空間が混在すると、どの名前空間に属するかを把握するのが難しくなります。
代わりに、必要な要素だけを個別にインポートすることを推奨します。
標準ライブラリヘッダー[編集]
- <algorithm>
- <any>
- <array>
- <atomic>
- <barrier>
- <bit>
- <bitset>
- <charconv>
- <chrono>
- <codecvt>
- <compare>
- <complex>
- <concepts>
- <condition_variable>
- <coroutine>
- <deque>
- <exception>
- <execution>
- <expected>
- <filesystem>
- <flat_map>
- <flat_set>
- <format>
- <forward_list>
- <fstream>
- <functional>
- <future>
- <generator>
- <initializer_list>
- <iomanip>
- <ios>
- <iosfwd>
- <iostream>
- <istream>
- <iterator>
- <latch>
- <limits>
- <list>
- <locale>
- <map>
- <mdspan>
- <memory>
- <memory_resource>
- <mutex>
- <new>
- <numbers>
- <numeric>
- <optional>
- <ostream>
- <print>
- <queue>
- <random>
- <ranges>
- <ratio>
- <regex>
- <scoped_allocator>
- <semaphore>
- <set>
- <shared_mutex>
- <source_location>
- <span>
- <spanstream>
- <sstream>
- <stack>
- <stacktrace>
- <stdexcept>
- <stdfloat>
- <stop_token>
- <streambuf>
- <string>
- <string_view>
- <strstream>
- <syncstream>
- <system_error>
- <thread>
- <tuple>
- <type_traits>
- <typeindex>
- <typeinfo>
- <unordered_map>
- <unordered_set>
- <utility>
- <valarray>
- <variant>
- <vector>
- <version>
- C言語互換ヘッダー
- C言語ヘッダーの先頭に c を補い末尾から .h を取り去る。
- <cassert>
- <cctype>
- <cerrno>
- <cfenv>
- <cfloat>
- <cinttypes>
- <climits>
- <clocale>
- <cmath>
- <csetjmp>
- <csignal>
- <cstdarg>
- <cstddef>
- <cstdint>
- <cstdio>
- <cstdlib>
- <cstring>
- <ctime>
- <cuchar>
- <cwchar>
- <cwctype>
- C言語ヘッダー
- <assert.h>
- <complex.h>
- <ctype.h>
- <errno.h>
- <fenv.h>
- <float.h>
- <inttypes.h>
- <iso646.h>
- <limits.h>
- <locale.h>
- <math.h>
- <setjmp.h>
- <signal.h>
- <stdalign.h>
- <stdarg.h>
- <stdatomic.h>
- <stdbool.h>
- <stddef.h>
- <stdint.h>
- <stdio.h>
- <stdlib.h>
- <string.h>
- <tgmath.h>
- <time.h>
- <uchar.h>
- <wchar.h>
- <wctype.h>
標準ライブラリヘッダー分類表 ヘッダー 分類 初出 説明 <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_t
とuintmax_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_chars
とstd::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_map
とstd::flat_multimap
コンテナアダプター<flat_set> コンテナ C++23 std::flat_set
とstd::flat_multiset
コンテナアダプター<forward_list> コンテナ C++11 std::forward_list
コンテナ<list> コンテナ - std::list
コンテナ<map> コンテナ - std::map
とstd::multimap
の連想コンテナ<mdspan> コンテナ C++23 std::mdspan
ビュー<queue> コンテナ - std::queue
とstd::priority_queue
のコンテナアダプター<set> コンテナ - std::set
とstd::multiset
の連想コンテナ<span> コンテナ C++20 std::span
ビュー<stack> コンテナ - std::stack
コンテナアダプター<unordered_map> コンテナ C++11 std::unordered_map
とstd::unordered_multimap
の非順序連想コンテナ<unordered_set> コンテナ C++11 std::unordered_set
とstd::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_fstream
、std::basic_ifstream
、std::basic_ofstream
クラステンプレートといくつかのtypedef<iomanip> 入出力 - 入出力のフォーマットを制御するヘルパー関数 <ios> 入出力 - std::ios_base
クラス、std::basic_ios
クラステンプレート、いくつかのtypedef<iosfwd> 入出力 - 入出力ライブラリのすべてのクラスの前方宣言 <iostream> 入出力 - 様々な標準ストリームオブジェクト <istream> 入出力 - std::basic_istream
クラステンプレート、いくつかのtypedef<ostream> 入出力 - std::basic_ostream
、std::basic_iostream
クラステンプレート、いくつかのtypedef<print> 入出力 C++23 書式付き出力ライブラリ( std::print
を含む)<spanstream> 入出力 C++23 std::basic_spanstream
、std::basic_ispanstream
、std::basic_ospanstream
クラステンプレート、typedef<sstream> 入出力 - std::basic_stringstream
、std::basic_istringstream
、std::basic_ostringstream
クラステンプレート、いくつかのtypedef<streambuf> 入出力 - std::basic_streambuf
クラステンプレート<syncstream> 入出力 C++20 std::basic_osyncstream
、std::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::vector
とstd::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_heap
、std::push_heap
、std::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::cin
とstd::cout
というストリームオブジェクトを使用して標準入力と標準出力を操作することができます。これらのストリームを使用することで、データの読み取りや表示を簡単に行うことができます。
ファイル入出力 (fstream)[編集]
ファイル入出力は、ファイルとプログラムの間でデータを読み書きするための機能です。C++の標準ライブラリでは、ファイル入出力ストリームを操作するためのstd::ifstream
とstd::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::byte
やstd::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_error
、std::logic_error
、std::invalid_argument
などがあります。これらのクラスは、特定の種類のエラーを表すために使用され、例外が送出された際にプログラムが適切に処理できるようにします。
その他の重要な機能[編集]
C++の標準ライブラリには、さまざまな追加機能が提供されています。以下では、その他の重要な機能について説明します。
時間と日付 (date and time)[編集]
時間と日付の操作は、多くのアプリケーションで重要な要素です。C++の標準ライブラリでは、時間や日付を表すためのstd::chrono
ライブラリが提供されています。このライブラリを使用することで、日付の取得、計算、比較などの操作を行うことができます。また、時間の測定や待機などの機能も提供されています。
メモリ管理 (memory management)[編集]
メモリ管理は、プログラムが動作するために必要なメモリの割り当てと解放を行う重要な要素です。C++の標準ライブラリでは、メモリ管理を行うための機能が提供されており、std::allocator
クラスやstd::shared_ptr
、std::unique_ptr
などのスマートポインタが使用されます。これらの機能を使用することで、メモリリークや二重解放などの問題を回避することができます。
スレッドと並行性 (threads and concurrency)[編集]
スレッドと並行性は、現代のプログラミングにおいて重要な要素です。C++の標準ライブラリでは、マルチスレッドプログラミングをサポートするための機能が提供されています。std::thread
クラスやstd::mutex
、std::condition_variable
などのクラスを使用することで、スレッド間の同期や通信を行うことができます。また、C++11以降では、スレッドプールや非同期タスクなどの機能も提供されています。
数学関数 (math functions)[編集]
数学関数は、科学技術計算やグラフィックスプログラミングなどの領域で広く使用されます。C++の標準ライブラリでは、数学関数を提供するための数多くの関数が提供されています。これには、三角関数、指数関数、対数関数、乱数生成などが含まれます。これらの関数を使用することで、数学的な計算を効率的に行うことができます。
ランダム数生成 (random number generation)[編集]
ランダム数生成は、シミュレーションやゲームなどの分野で広く使用されます。C++の標準ライブラリでは、ランダム数を生成するためのさまざまな機能が提供されています。これには、線形合同法やメルセンヌ・ツイスターなどのアルゴリズムを使用した乱数生成器が含まれます。また、乱数生成器を使用して特定の範囲の乱数を生成する機能も提供されています。
標準ライブラリの最適化[編集]
標準ライブラリの最適化は、プログラムのパフォーマンスを向上させるために重要なステップです。以下では、標準ライブラリを使用する際の最適化について説明します。
使用時の注意点[編集]
標準ライブラリを使用する際に注意するべきポイントがいくつかあります。まず、適切なコンテナやアルゴリズムを選択することが重要です。特定の操作に適したコンテナやアルゴリズムを選択することで、効率的なプログラムを作成することができます。また、不要なコピーの回避やムーブセマンティクスの活用など、効率的なプログラミング手法を採用することも重要です。
さらに、標準ライブラリの使用に伴うオーバーヘッドにも注意が必要です。標準ライブラリは一般的に汎用的な実装を提供していますが、特定の状況においてはカスタム実装がより効率的な場合があります。プログラムの特性や要件に応じて、標準ライブラリの使用を最適化することが重要です。
パフォーマンスの向上方法[編集]
標準ライブラリのパフォーマンスを向上させるためには、いくつかの方法があります。まず、最適化フラグを使用してコンパイラに最適化を指示することが重要です。最適化フラグを適切に設定することで、コンパイル時に効率的なコードが生成される可能性が高まります。
また、コンテナやアルゴリズムの選択によってもパフォーマンスを向上させることができます。例えば、ベクターやアレイなどの連続したメモリ配置を持つコンテナは、ランダムアクセスやイテレーションが高速に行えるため、大量のデータを効率的に処理する際に適しています。さらに、アルゴリズムの選択によってもパフォーマンスを向上させることができます。例えば、ソートアルゴリズムや探索アルゴリズムの選択によって、処理速度を向上させることができます。
さらに、並列処理やメモリ管理の最適化など、他の最適化手法も検討する価値があります。並列処理を使用することで、複数のスレッドを使用して処理を並列化することができ、処理速度を向上させることができます。また、メモリ管理の最適化を行うことで、不要なメモリの割り当てや解放を減らすことができ、プログラムのパフォーマンスを向上させることができます。
外部リンク[編集]