Namespaces
Variants

Default arguments

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Ermöglicht es, eine Funktion aufzurufen, ohne einen oder mehrere nachfolgende Argumente anzugeben.

Angezeigt durch die Verwendung der folgenden Syntax für einen Parameter in der parameter-list einer function declaration .

attr  (optional) decl-specifier-seq declarator = initializer (1)
attr  (optional) decl-specifier-seq abstract-declarator  (optional) = initializer (2)
**Anmerkung:** Die Übersetzung war nicht erforderlich, da der Text hauptsächlich aus C++-spezifischen Begriffen und HTML-Tags besteht, die gemäß den Anweisungen unverändert bleiben sollten. Die einzigen übersetzbaren Elemente "(optional)" wurden bereits in der ursprünglichen deutschen Version verwendet.

Standardargumente werden anstelle der fehlenden nachgestellten Argumente in einem Funktionsaufruf verwendet:

void point(int x = 3, int y = 4);
point(1, 2); // ruft point(1, 2) auf
point(1);    // ruft point(1, 4) auf
point();     // ruft point(3, 4) auf

In einer Funktionsdeklaration müssen nach einem Parameter mit einem Standardargument alle nachfolgenden Parameter:

  • haben ein Standardargument, das in dieser oder einer vorherigen Deklaration aus demselben Gültigkeitsbereich angegeben wurde:
int x(int = 1, int); // Fehler: Nur die nachfolgenden Parameter können Standardargumente haben
                     //        (angenommen, es gibt keine vorherige Deklaration von „x“)
void f(int n, int k = 1);
void f(int n = 0, int k); // OK: Das Standardargument von „k“ wird durch
                          // die vorherige Deklaration im selben Gültigkeitsbereich bereitgestellt
void g(int, int = 7);
void h()
{
    void g(int = 1, int); // Fehler: Nicht derselbe Gültigkeitsbereich
}
  • ...es sei denn, der Parameter wurde aus einem Parameter-Pack expandiert:
template<class... T>
struct C { void f(int n = 0, T...); };
C<int> c;  // OK; instantiates declaration void C::f(int n = 0, int)
  • oder ein Funktionsparameter-Pack sein:
template<class... T>
void h(int i = 0, T... args); // OK
(seit C++11)

Die Ellipse ist kein Parameter und kann daher auf einen Parameter mit einem Standardargument folgen:

int g(int n = 0, ...); // OK

Standardargumente sind nur in den Parameterlisten von Funktionsdeklarationen und Lambda-Ausdrücken erlaubt, (seit C++11) und sind nicht zulässig in Deklarationen von Zeigern auf Funktionen, Referenzen auf Funktionen oder in typedef -Deklarationen. Template-Parameterlisten verwenden eine ähnliche Syntax für ihre Standard-Template-Argumente .

Für nicht-template Funktionen können Standardargumente zu einer Funktion hinzugefügt werden, die bereits deklariert wurde, wenn die Funktion im selben Scope erneut deklariert wird. An der Stelle eines Funktionsaufrufs sind die Standardargumente eine Vereinigung der Standardargumente, die in allen sichtbaren Deklarationen für die Funktion bereitgestellt werden. Eine erneute Deklaration kann kein Standardargument für einen Parameter einführen, für den bereits ein Standardargument sichtbar ist (selbst wenn der Wert derselbe ist). Eine erneute Deklaration in einem inneren Scope übernimmt nicht die Standardargumente aus äußeren Scopes.

void f(int, int);     // #1
void f(int, int = 7); // #2 OK: fügt ein Standardargument hinzu
void h()
{
    f(3); // #1 und #2 sind im Gültigkeitsbereich; führt einen Aufruf von f(3,7) aus
    void f(int = 1, int); // Fehler: Das Standardargument des zweiten
                          // Parameters wird nicht von äußeren Gültigkeitsbereichen übernommen
}
void m()
{ // neuer Gültigkeitsbereich beginnt
    void f(int, int); // Deklaration im inneren Gültigkeitsbereich; hat kein Standardargument.
    f(4); // Fehler: Nicht genügend Argumente für den Aufruf von f(int, int)
    void f(int, int = 6);
    f(4); // OK: ruft f(4, 6) auf;
    void f(int, int = 6); // Fehler: Der zweite Parameter hat bereits ein
                          // Standardargument (selbst wenn die Werte identisch sind)
}
void f(int = 1, int); // #3 OK, fügt ein Standardargument zu #2 hinzu
void n()
{ // neuer Gültigkeitsbereich beginnt
    f(); // #1, #2 und #3 sind im Gültigkeitsbereich: ruft f(1, 7) auf;
}

Wenn eine inline Funktion in verschiedenen Übersetzungseinheiten deklariert wird, müssen die kumulierten Sätze von Standardargumenten am Ende jeder Übersetzungseinheit identisch sein.

Wenn eine nicht-inline Funktion im selben Namensbereich in verschiedenen Übersetzungseinheiten deklariert wird, müssen die entsprechenden Standardargumente, falls vorhanden, identisch sein (aber einige Standardargumente können in einigen Übersetzungseinheiten fehlen).

(since C++20)

Wenn eine friend -Deklaration einen Standardargument angibt, muss es sich um eine Friend-Funktionsdefinition handeln, und es sind keine weiteren Deklarationen dieser Funktion in der Übersetzungseinheit zulässig.

Die using-declarations überträgt den Satz bekannter Standardargumente, und wenn später dem Namensraum der Funktion weitere Standardargumente hinzugefügt werden, sind diese Standardargumente ebenfalls überall sichtbar, wo die using-declaration sichtbar ist:

namespace N
{
    void f(int, int = 1);
}
using N::f;
void g()
{
    f(7); // ruft f(7, 1) auf;
    f();  // Fehler
}
namespace N
{
    void f(int = 2, int);
}
void h()
{
    f();  // ruft f(2, 1) auf;
}
**Übersetzte Kommentare:** - `// calls f(7, 1);` → `// ruft f(7, 1) auf;` - `// error` → `// Fehler` - `// calls f(2, 1);` → `// ruft f(2, 1) auf;` **Beibehalten:** - Alle HTML-Tags und Attribute - C++ Code innerhalb der `
` Tags
- C++ spezifische Begriffe (namespace, void, int, etc.)
- Formatierung und Struktur

Die in den Standardargumenten verwendeten Namen werden am Punkt der Deklaration gesucht, auf Zugriff geprüft und gebunden, aber am Punkt des Funktionsaufrufs ausgeführt:

int a = 1;
int f(int);
int g(int x = f(a)); // Suche nach f findet ::f, Suche nach a findet ::a
                     // der Wert von ::a, der zu diesem Zeitpunkt 1 beträgt, wird nicht verwendet
void h()
{
    a = 2; // ändert den Wert von ::a
    {
        int a = 3;
        g(); // ruft f(2) auf, dann ruft g() mit dem Ergebnis auf
    }
}

Für eine Memberfunktion einer nicht- templatisierten Klasse sind Standardargumente in der Out-of-Class-Definition erlaubt und werden mit den Standardargumenten kombiniert, die durch die Deklaration im Klassenkörper bereitgestellt werden. Wenn diese Out-of-Class-Standardargumente eine Memberfunktion in einen Standardkonstruktor oder Kopier- /Move- (seit C++11) Konstruktor/Zuweisungsoperator verwandeln würden (was den Aufruf mehrdeutig macht), ist das Programm fehlerhaft. Für Memberfunktionen von templatisierten Klassen müssen alle Standardargumente in der ursprünglichen Deklaration der Memberfunktion bereitgestellt werden.

class C
{
    void f(int i = 3);
    void g(int i, int j = 99);
    C(int arg); // Nicht-Standard-Konstruktor
};
void C::f(int i = 3) {}         // Fehler: Standardargument bereits
                                // im Klassenbereich angegeben
void C::g(int i = 88, int j) {} // OK: In dieser Übersetzungseinheit
                                // kann C::g ohne Argument aufgerufen werden
C::C(int arg = 1) {}            // Fehler: Macht dies zu einem Standardkonstruktor

Die Überschreiber von virtual Funktionen übernehmen nicht die Standardargumente aus den Basisklassen-Deklarationen, und wenn der virtuelle Funktionsaufruf erfolgt, werden die Standardargumente basierend auf dem statischen Typ des Objekts bestimmt (Hinweis: dies kann mit dem Non-Virtual Interface Pattern vermieden werden).

struct Base
{
    virtual void f(int a = 7);
};
struct Derived : Base
{
    void f(int a) override;
};
void m()
{
    Derived d;
    Base& b = d;
    b.f(); // OK: ruft Derived::f(7) auf
    d.f(); // Fehler: kein Standardargument
}

Lokale Variablen sind in Standardargumenten nicht erlaubt, es sei denn, sie werden nicht ausgewertet :

void f()
{
    int n = 1;
    extern void g(int x = n); // Fehler: Lokale Variable kann kein Standardargument sein
    extern void h(int x = sizeof n); // OK laut CWG 2082
}

Der this -Zeiger ist in Standardargumenten nicht erlaubt:

class A
{
    void f(A* p = this) {} // Fehler: dies ist nicht erlaubt
};

Nicht-statische Klassenmember sind in Standardargumenten nicht erlaubt (selbst wenn sie nicht ausgewertet werden), außer wenn sie zur Bildung eines Zeigers-auf-Member oder in einem Member-Zugriffsausdruck verwendet werden:

int b;
class X
{
    int a;
    int mem1(int i = a); // Fehler: nicht-statisches Mitglied kann nicht verwendet werden
    int mem2(int i = b); // OK: Suche findet X::b, das statische Mitglied
    int mem3(int X::* i = &X::a); // OK: nicht-statisches Mitglied kann verwendet werden
    int mem4(int i = x.a); // OK: in einem Mitgliedszugriffsausdruck
    static X x;
    static int b;
};

Ein Standardargument wird jedes Mal ausgewertet, wenn die Funktion ohne Argument für den entsprechenden Parameter aufgerufen wird. Funktionsparameter sind in Standardargumenten nicht zulässig, es sei denn, sie werden nicht ausgewertet . Beachten Sie, dass Parameter, die früher in der Parameterliste erscheinen, im Scope liegen:

int a;
int f(int a, int b = a); // Fehler: Der Parameter a wird in einem Standardargument verwendet
int g(int a, int b = sizeof a); // Fehler bis zur Lösung von CWG 2082
                                // OK nach der Lösung: Verwendung in nicht-ausgewertetem Kontext ist OK

Die Standardargumente sind nicht Teil des Funktionstyps:

int f(int = 0);
void h()
{
    int j = f(1);
    int k = f(); // ruft f(0) auf;
}
int (*p1)(int) = &f;
int (*p2)()    = &f; // Fehler: Der Typ von f ist int(int)

Operatorfunktionen außer dem Funktionsaufrufoperator und dem Subskriptoperator (seit C++23) können keine Standardargumente haben:

class C
{
    int operator++(int i = 0); // fehlerhaft
    int operator[](int j = 0); // OK seit C++23
    int operator()(int k = 0); // OK
};

Explizite Objektparameter können keine Standardargumente haben:

struct S { void f(this const S& = S{}); }; // ill-formed
(seit C++23)

Hinweis

Leerzeichen können erforderlich sein, um einen zusammengesetzten Zuweisungsoperator zu vermeiden, wenn der Parametername fehlt (siehe maximal munch ).

void f1(int*=0);         // Fehler, „*=“ ist hier unerwartet
void g1(const int&=0);   // Fehler, „&=“ ist hier unerwartet
void f2(int* = 0);       // OK
void g2(const int& = 0); // OK
void h(int&&=0);         // OK auch ohne Leerzeichen, „&&“ ist hier ein Token

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
CWG 217 C++98 ein Standardargument konnte zu einer Nicht-
Template-Memberfunktion einer Klassenvorlage hinzugefügt werden
verboten
CWG 1344 C++98 in der Out-of-Class-Definition hinzugefügte Standardargumente könnten
diese in eine spezielle Memberfunktion ändern
verboten
CWG 1716 C++98 Standardargumente wurden bei jedem Aufruf der Funktion
ausgewertet, selbst wenn der Aufrufer Argumente bereitstellte
nur ausgewertet, wenn kein
Argument für den entsprechenden
Parameter bereitgestellt wird
CWG 2082 C++98 Standardargumenten war verboten, lokale Variablen
und vorhergehende Parameter in nicht-ausgewertetem Kontext zu verwenden
Verwendung in nicht-ausgewertetem
Kontext erlaubt
CWG 2233 C++11 aus Parameterpaketen expandierte Parameter konnten
nicht nach Parametern mit Standardargumenten erscheinen
erlaubt
CWG 2683 C++98 Out-of-Class-Definitionen der Memberfunktionen von
verschachtelten Klassen von Klassenvorlagen konnten Standardargumente haben
verboten