デフォルト引数
末尾の引数を1つ以上提供せずに関数を呼ぶことを可能とします。
関数宣言の parameter-list で引数に対して以下の構文を用いることによって指定されます。
attr(オプション) decl-specifier-seq declarator = initializer
|
(1) | ||||||||
attr(オプション) decl-specifier-seq abstract-declarator(オプション) = initializer
|
(2) | ||||||||
デフォルト引数は関数呼び出しで末尾の引数が欠けている場所で使用されます。
void point(int x = 3, int y = 4);
point(1,2); // point(1,2) を呼びます。
point(1); // point(1,4) を呼びます。
point(); // point(3,4) を呼びます。
関数宣言において、デフォルト引数付きの引数の後、すべての後続の引数は、以下を満たさなければなりません。
- この宣言または同じスコープの以前の宣言から供給されるデフォルト引数を持つ。
int x(int = 1, int); // エラー (x の以前の宣言はないと仮定しています)。
void f(int n, int k = 1);
void f(int n = 0, int k); // OK、 k のデフォルトは同じスコープの以前の宣言から供給されます。
void g(int, int = 7);
void h() {
void g(int = 1, int); // エラー、同じスコープではありません。
}
template<class ...T> struct C { void f(int n = 0, T...); };
C<int> c; // OK、宣言 void C::f(int n = 0, int) を実体化します。
template<class...T> void h(int i = 0, T... args); // OK。
|
(C++11以上) |
省略記号は引数ではなく、そのためデフォルト引数を持つ引数の後に置くことができます。
int g(int n = 0, ...); // OK。
デフォルト引数は関数宣言およびラムダ式 (C++14以上)の引数リストでのみ使用でき、関数へのポインタの宣言、関数への参照の宣言、または typedef 宣言では使用できません。 テンプレート引数リストはデフォルトテンプレート引数に対して同様の構文を使用します。
非テンプレート関数では、関数が同じスコープで再宣言された場合、すでに宣言された関数にデフォルト引数を追加できます。 関数呼び出しの地点においては、デフォルト引数はその関数に対するすべての可視な宣言で提供されるデフォルト引数の和です。 再宣言はデフォルトがすでに可視である引数に対してデフォルトを導入することはできません (たとえ値が同じであっても)。 内側のスコープ内の再宣言は外側のスコープからデフォルト引数を取得しません。
void f(int, int); // #1
void f(int, int = 7); // #2 OK、デフォルトを追加します。
void h() {
f(3); // #1 と #2 が可視です。 f(3,7) の呼び出しを行います。
void f(int = 1, int); // エラー、内側のスコープの宣言はデフォルトを取得しません。
}
void m() { // 新たなスコープが始まります。
void f(int, int); // 内側のスコープの宣言。 デフォルトを持ちません。
f(4); // エラー、 f(int, int) を呼ぶために十分な引数がありません。
void f(int, int = 6);
f(4); // OK、 f(4,6); を呼びます。
void f(int, int = 6); // エラー、同じスコープでデフォルトを再宣言できません。
}
void f(int = 1, int); // #3 OK、 #2 にデフォルトを追加します。
void n() { // 新たなスコープが始まります。
f(); // #1、 #2、および #3 が可視です。 f(1, 7); を呼びます。
}
異なる翻訳単位でインライン関数が宣言された場合、デフォルト引数の累積された集合は各翻訳単位の終わりで同じでなければなりません。
|
非インライン関数が異なる翻訳単位内の同じ名前空間スコープ内で宣言された場合、対応するデフォルト引数は、もし存在するならば、同じでなければなりません (一部の翻訳単位内で一部のデフォルト引数が欠けていても構いません)。 |
(C++20以上) |
フレンド宣言がデフォルトを指定する場合、それはフレンド関数の定義でなければならず、その翻訳単位内ではその関数の他の宣言は許されません。
using 宣言は既知のデフォルト引数の集合を持ち越します。 その関数の名前空間に後程さらなる引数が追加された場合、それらのデフォルトも using 宣言が可視なあらゆる場所で可視になります。
namespace N {
void f(int, int = 1);
}
using N::f;
void g() {
f(7); // f(7, 1); を呼びます。
f(); // エラー。
}
namespace N {
void f(int = 2, int);
}
void h() {
f(); // f(2, 1); を呼びます。
}
デフォルト引数で使用される名前は、宣言の時点で名前探索され、