Namensräume
Varianten
Aktionen

Standardargumente

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Ermöglicht den Aufruf einer Funktion, ohne ein oder mehrere nachfolgende Argumente anzugeben.

Angezeigt durch die Verwendung der folgenden Syntax für einen Parameter in der Parameterliste einer Funktionsdeklaration.

attr (optional) decl-specifier-seq declarator = initializer (1)
attr (optional) decl-specifier-seq abstract-declarator (optional) = initializer (2)

Standardargumente werden anstelle der fehlenden nachfolgenden Argumente in einem Funktionsaufruf verwendet.

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

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

  • ein Standardargument, das in dieser oder einer früheren Deklaration aus demselben Gültigkeitsbereich angegeben ist, aufweisen
int x(int = 1, int); // Error: only the trailing parameters can have default arguments
                     //        (assuming there's no previous declaration of “x”)
 
void f(int n, int k = 1);
void f(int n = 0, int k); // OK: the default argument of “k” is provided by
                          // the previous declaration in the same scope
 
void g(int, int = 7);
 
void h()
{
    void g(int = 1, int); // Error: not the same scope
}
  • ...es sei denn, der Parameter wurde aus einem Parameterpaket erweitert
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 Funktionsparameterpaket sein
template<class... T>
void h(int i = 0, T... args); // OK
(seit C++11)

Die Auslassungspunkte sind kein Parameter und können daher einem 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 nicht in Deklarationen von Funktionszeigern, Funktionsreferenzen oder in typedef-Deklarationen erlaubt. Vorlagenteilnehmerlisten verwenden eine ähnliche Syntax für ihre Standard-Vorlagenargumente.

Für Nicht-Vorlagenfunktionen können Standardargumente zu einer bereits deklarierten Funktion hinzugefügt werden, wenn die Funktion im selben Gültigkeitsbereich neu deklariert wird. Zum Zeitpunkt eines Funktionsaufrufs sind die Standardargumente eine Vereinigung der Standardargumente, die in allen sichtbaren Deklarationen für die Funktion angegeben sind. Eine Neudeklaration kann kein Standardargument für einen Parameter einführen, für den bereits ein Standardargument sichtbar ist (auch wenn der Wert derselbe ist). Eine Neudeklaration in einem inneren Gültigkeitsbereich erwirbt keine Standardargumente aus äußeren Gültigkeitsbereichen.

void f(int, int);     // #1
void f(int, int = 7); // #2 OK: adds a default argument
 
void h()
{
    f(3); // #1 and #2 are in scope; makes a call to f(3,7)
    void f(int = 1, int); // Error: the default argument of the second
                          // parameter is not acquired from outer scopes
}
 
void m()
{ // new scope begins
    void f(int, int); // inner scope declaration; has no default argument.
    f(4); // Error: not enough arguments to call f(int, int)
    void f(int, int = 6);
    f(4); // OK: calls f(4, 6);
    void f(int, int = 6); // Error: the second parameter already has a
                          // default argument (even if the values are the same)
}
 
void f(int = 1, int); // #3 OK, adds a default argument to #2
 
void n()
{ // new scope begins
    f(); // #1, #2, and #3 are in scope: calls f(1, 7);
}

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

Wenn eine Nicht-Inline-Funktion im selben Namespace-Gültigkeitsbereich in verschiedenen Übersetzungseinheiten deklariert wird, müssen die entsprechenden Standardargumente gleich sein, wenn sie vorhanden sind (einige Standardargumente können jedoch in einigen TU fehlen).

(seit C++20)

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

Using-Deklarationen übernehmen den Satz bekannter Standardargumente, und wenn später weitere Standardargumente zur Funktion hinzugefügt werden, sind diese ebenfalls überall dort sichtbar, wo die Using-Deklaration sichtbar ist.

namespace N
{
    void f(int, int = 1);
}
 
using N::f;
 
void g()
{
    f(7); // calls f(7, 1);
    f();  // error
}
 
namespace N
{
    void f(int = 2, int);
}
 
void h()
{
    f();  // calls f(2, 1);
}

Die Namen, die in den Standardargumenten verwendet werden, werden bei der Deklaration nachgeschlagen, auf Zugriffsberechtigungen geprüft und gebunden, aber bei dem Funktionsaufruf ausgeführt.

int a = 1;
 
int f(int);
 
int g(int x = f(a)); // lookup for f finds ::f, lookup for a finds ::a
                     // the value of ::a, which is 1 at this point, is not used
 
void h()
{
    a = 2; // changes the value of ::a
    {
        int a = 3;
        g(); // calls f(2), then calls g() with the result
    }
}

Für eine Member-Funktion einer nicht-vorlagenbezogenen Klasse sind die Standardargumente in der Definition außerhalb der Klasse erlaubt und werden mit den Standardargumenten kombiniert, die durch die Deklaration innerhalb des Klassenkörpers bereitgestellt werden. Wenn diese Standardargumente außerhalb der Klasse einen Member-Funktion in einen Standardkonstruktor oder Kopier-/Verschiebe-(seit C++11)Konstruktor/Zuweisungsoperator (was den Aufruf mehrdeutig macht) verwandeln, ist das Programm fehlerhaft. Für Member-Funktionen von Vorlagenklassen müssen alle Standardargumente in der ursprünglichen Deklaration der Member-Funktion bereitgestellt werden.

class C
{
    void f(int i = 3);
    void g(int i, int j = 99);
    C(int arg); // non-default constructor
};
 
void C::f(int i = 3) {}         // error: default argument already
                                // specified in class scope
 
void C::g(int i = 88, int j) {} // OK: in this translation unit,
                                // C::g can be called with no argument
 
C::C(int arg = 1) {}            // Error: turns this into a default constructor

Die Überschreiber von virtuellen Funktionen erwerben keine 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 Nicht-virtuelles Schnittstellenmuster 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: calls Derived::f(7)
    d.f(); // Error: no default argument
}

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); // error: local variable cannot be a default argument
    extern void h(int x = sizeof n); // OK as of CWG 2082
}

Der this-Zeiger ist in Standardargumenten nicht erlaubt.

class A
{
    void f(A* p = this) {} // error: this is not allowed
};

Nicht-statische Klassenmitglieder sind in Standardargumenten nicht erlaubt (auch wenn sie nicht ausgewertet werden), außer wenn sie zur Bildung eines Zeigers auf ein Mitglied oder in einem Member-Zugriffs-Ausdruck verwendet werden.

int b;
 
class X
{
    int a;
    int mem1(int i = a); // error: non-static member cannot be used
    int mem2(int i = b); // OK: lookup finds X::b, the static member
    int mem3(int X::* i = &X::a); // OK: non-static member can be used
    int mem4(int i = x.a); // OK: in a member access expression
 
    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 erlaubt, es sei denn, sie werden nicht ausgewertet. Beachten Sie, dass früher in der Parameterliste erscheinende Parameter im Gültigkeitsbereich liegen.

int a;
 
int f(int a, int b = a); // Error: the parameter a used in a default argument
 
int g(int a, int b = sizeof a); // Error until resolving CWG 2082
                                // OK after resolution: use in unevaluated context is OK

Die Standardargumente sind kein Teil des Funktionstyps.

int f(int = 0);
 
void h()
{
    int j = f(1);
    int k = f(); // calls f(0);
}
 
int (*p1)(int) = &f;
int (*p2)()    = &f; // Error: the type of f is int(int)

Operatorfunktionen, außer dem Funktionsaufruf-Operator und dem Subskriptionsoperator(seit C++23), können keine Standardargumente haben.

class C
{
    int operator++(int i = 0); // ill-formed
    int operator[](int j = 0); // OK since 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)

[bearbeiten] Hinweis

Leerzeichen können notwendig sein, um ein zusammengesetztes Zuweisungstoken zu vermeiden, wenn der Parametername fehlt (siehe Maximal Munch).

void f1(int*=0);         // Error, “*=” is unexpected here
void g1(const int&=0);   // Error, “&=” is unexpected here
void f2(int* = 0);       // OK
void g2(const int& = 0); // OK
void h(int&&=0);         // OK even without spaces, “&&” is a token here

[bearbeiten] Fehlerberichte

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

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 217 C++98 ein Standardargument konnte zu einem Nicht-
Vorlagen-Member einer Klassen-Vorlage hinzugefügt werden.
verboten
CWG 1344 C++98 in der Definition außerhalb der Klasse hinzugefügte Standardargumente einer
Member-Funktion konnten diese zu einer speziellen Member-Funktion ändern.
verboten
CWG 1716 C++98 Standardargumente wurden jedes Mal ausgewertet, wenn die Funktion
aufgerufen wurde, auch wenn der Aufrufer die Argumente bereitstellte.
nur ausgewertet, wenn kein
Argument für den
entsprechenden Parameter bereitgestellt wird.
CWG 2082 C++98 Standardargumente waren verboten, lokale Variablen zu verwenden
und vorherige Parameter in einem nicht ausgewerteten Kontext.
nicht ausgewerteter Kontext
erlaubt verwendet.
CWG 2233 C++11 aus Parameterpaketen erweiterte Parameter konnten
nicht nach Parametern mit Standardargumenten erscheinen.
erlaubt
CWG 2683 C++98 Definitionen von Member-Funktionen von Klassen-Vorlagen von verschachtelten Klassen außerhalb der Klasse konnten Standardargumente haben.
Klassen von Vorlagen von verschachtelten Klassen konnten Standardargumente haben.
verboten