C++教科書/標準ライブラリ編/<cstdarg>の章
編集はじめに
編集C++の標準ライブラリには、可変長引数をサポートする <cstdarg>
ヘッダーが用意されています。このヘッダーは、主に関数に対して可変長の引数を渡す際に使用されます。可変長引数を扱うための型やマクロが定義されています。
va_listの説明
編集va_list
型は、可変長引数のリストを表現する型です。この型のオブジェクトは、va_start
、va_arg
、va_end
、va_copy
マクロで操作されます。
va_start マクロ
編集va_start
マクロは、可変長引数のリストの処理を開始する際に呼び出します。以下は使用例です。
#include <cstdarg> void printInts(int count, ...) { va_list args; va_start(args, count); // args を初期化 for (int i = 0; i < count; i++) { int value = va_arg(args, int); // 次の引数を int 型として取得 printf("%d ", value); } va_end(args); // args の処理を終了 } int main() { printInts(5, 1, 2, 3, 4, 5); // 出力: 1 2 3 4 5 return 0; }
va_arg マクロ
編集va_arg
マクロは、可変長引数リストから次の引数を取得します。第2引数で型を指定する必要があります。
double average(int count, ...) { va_list args; va_start(args, count); double sum = 0; for (int i = 0; i < count; i++) { sum += va_arg(args, double); // 次の引数を double 型として取得 } va_end(args); return sum / count; }
va_copy マクロ (C++11から)
編集va_copy
マクロは、可変長引数リストのコピーを作成します (C++11から利用可能)。
#include <cstdarg> double sum(int count, ...) { va_list args, args_copy; va_start(args, count); va_copy(args_copy, args); // args_copy を args のコピーとして初期化 double result = 0; for (int i = 0; i < count; i++) { result += va_arg(args_copy, double); } va_end(args_copy); va_end(args); return result; }
va_end マクロ
編集va_end
マクロは、可変長引数リストの処理を終了する際に呼び出します。
可変長引数関数の実装例
編集可変長引数を使った関数の具体例を示します。
- シンプルな例
#include <cstdarg> #include <iostream> int sum(int count, ...) { int result = 0; va_list args; va_start(args, count); for (int i = 0; i < count; i++) { result += va_arg(args, int); } va_end(args); return result; } int main() { std::cout << sum(3, 1, 2, 3) << std::endl; // 6 std::cout << sum(5, 4, 8, 3, 7, 1) << std::endl; // 23 return 0; }
- 応用的な例
#include <cstdarg> #include <iostream> #include <string> std::string concatenate(const std::string& first, ...) { std::string result = first; va_list args; va_start(args, first); const char* str = va_arg(args, const char*); while (str != nullptr) { result += str; str = va_arg(args, const char*); } va_end(args); return result; } int main() { std::cout << concatenate("Hello", ", ", "world", "!") << std::endl; // Hello, world! std::cout << concatenate("C++", " ", "is", " ", "awesome", nullptr) << std::endl; // C++ is awesome return 0; }
可変長引数の安全性と注意点
編集可変長引数は型安全性が欠如しているため、引数の型が合っていないと未定義動作が発生する可能性があります。また、引数の数を正しく管理する必要があります。
可変長引数は、使い勝手の良さと柔軟性を持つ反面、安全性に欠けるトレードオフがあります。C++11から導入された可変長テンプレートは、可変長引数に比べてより型安全で扱いやすい機能です。
まとめ
編集<cstdarg>
ヘッダーでは、可変長引数をサポートするための va_list
型と va_start
、va_arg
、va_copy
、va_end
マクロが提供されています。可変長引数は柔軟性が高い一方で、型安全性が低いというトレードオフがあります。C++11以降では、可変長テンプレートが可変長引数に比べてより安全で便利な機能として導入されています。また、std::initilize_list
の使用も検討に値します。