C++/スコープ
< C++
導入
編集スコープとは何か?
編集プログラミングにおける「スコープ」とは、変数や関数が有効な範囲を定義する概念です。スコープは、変数や関数が宣言された場所によって決定され、それによってその変数や関数へのアクセス範囲が決まります。
スコープがコード内でどのように機能するかの概要
編集スコープは、コード内で変数や関数の可視性と生存期間を制御します。これにより、同じ名前の変数や関数が異なる場所で定義された場合でも、それぞれのスコープ内でのみアクセス可能であり、名前の衝突を避けることができます。
モダンC++におけるスコープ
編集基本的なスコープの種類
編集C++20以降では、以下の主要なスコープタイプが定義されています:
- ブロックスコープ - 中括弧
{}
で囲まれた範囲 - 関数スコープ - 関数内全体
- 名前空間スコープ - 名前空間内全体
- クラススコープ - クラス定義内
- ファイルスコープ - ソースファイル内
- モジュールスコープ (C++20以降) - モジュール内
ブロックスコープ
編集ブロックスコープの定義
編集ブロックスコープは、中括弧{}
で囲まれたコードブロック内で有効なスコープです。C++17以降では、初期化文を持つif
文やswitch
文でも独自のスコープを形成できます。
ブロックスコープ内での変数の有効性
編集ブロックスコープ内で宣言された変数は、そのブロック内でのみ有効です。C++17以降、構造化束縛宣言もブロックスコープに従います。
auto main() -> int { if (auto [x, y] = std::pair{1, 2}; x > 0) { // C++17構造化束縛 // xとyはこのブロック内でのみ有効 } return 0; }
for文スコープ
編集コード例(forループ内のスコープ)
編集C++20では、range-based for
ループでの初期化文もサポートされています:
auto main() -> int { std::vector<int> vec{1, 2, 3}; for (std::size_t i = 0; auto& elem : vec) { // C++20 std::cout << i++ << ": " << elem << '\n'; } return 0; }
名前空間
編集モダンな名前空間の使用
編集C++17以降では、入れ子名前空間を簡略化して記述できます:
namespace MyCompany::MyLibrary::MyFeature { // C++17 // 機能の実装 }
また、C++20では、モジュール内での名前空間の扱いも定義されています。
モジュールスコープ (C++20)
編集モジュールスコープの概要
編集C++20で導入されたモジュールは、新しいスコープレベルを提供します:
module; // グローバルモジュールフラグメント #include <string> export module my.module; // モジュール宣言 export namespace MyModule { auto getValue() -> std::string { return "Hello from module"; } }
コンセプトとスコープ (C++20)
編集コンセプトの可視性
編集C++20で導入されたコンセプトも、通常の名前空間規則に従います:
export module my.concepts; export template<typename T> concept Printable = requires(T t) { { std::cout << t } -> std::same_as<std::ostream&>; };
スコープとクラス
編集モダンC++でのクラススコープ
編集C++20以降、コンセプトやモジュールとの相互作用を含む、より豊かなクラススコープの機能が利用可能です:
export class MyClass { constexpr static int value = 42; public: auto getValue() const -> int requires std::is_constant_evaluated() { return value; } };
演習問題
編集- モジュールとクラススコープを組み合わせて使用し、モジュールをエクスポートする例を作成してください。
- C++20のコンセプトを使用して、特定の型に対する要件を定義し、それをテンプレート関数で使用する例を作成してください。
- 構造化束縛を使用して、複数の戻り値を持つ関数の結果を受け取り、それらの値をブロックスコープ内で使用する例を作成してください。