Namensräume
Varianten
Aktionen

Variadische Argumente

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 einer Funktion, eine beliebige Anzahl zusätzlicher Argumente anzunehmen.

Eine Funktion ist variadisch, wenn der letzte Parameter ihrer Parameterliste ein Auslassungszeichen (...) ist.

Das Komma vor dem Auslassungszeichen kann weggelassen werden. (veraltet in C++26)
// the function declared as follows
int printx(const char* fmt, ...);
int printx(const char* fmt...); // same as above, but deprecated since C++26
 
// may be called with one or more arguments:
printx("hello world");
printx("a=%d b=%d", a, b);
 
int printy(..., const char* fmt); // error: ... can only be the last parameter
int printz(...); // valid, but the arguments cannot be accessed portably

Dies unterscheidet sich von einer Parameterpaketexpansion einer Funktion, die durch ein Auslassungszeichen angezeigt wird, das Teil eines Deklarators ist, anstatt dass ein Auslassungszeichen allein ein Parameter ist. Sowohl Parameterpaketexpansion als auch das „variadische“ Auslassungszeichen können in der Deklaration einer Funktion-Vorlage vorkommen, wie im Fall von std::is_function.

(seit C++11)

Inhalt

[bearbeiten] Standard-Argument-Promotions

Wenn eine variadische Funktion aufgerufen wird, durchlaufen nach lvalue-zu-rvalue, Array-zu-Zeiger und Funktion-zu-Zeiger Konvertierungen alle Argumente, die Teil der variablen Argumentliste sind, zusätzliche Konvertierungen, die als *Standard-Argument-Promotions* bezeichnet werden.

(seit C++11)
  • float-Argumente werden wie bei der Gleitkomma-Promotion in double konvertiert.
  • bool, char, short und nicht-scoped Aufzählungen werden wie bei der Ganzzahl-Promotion in int oder breitere Ganzzahldatentypen konvertiert.

Nicht-POD-Klassentypen(bis C++11)Scoped Aufzählungen und Klassentypen mit einem geeigneten nicht-trivialen Kopierkonstruktor, einem geeigneten nicht-trivialen Move-Konstruktor oder einem nicht-trivialen Destruktor(seit C++11) sind in potenziell ausgewerteten Aufrufen bedingt unterstützt mit implementierungsdefinierten Semantiken (diese Typen werden in unevaluierten Aufrufen immer unterstützt).

Da variadische Parameter für die Überladungsauflösung den niedrigsten Rang haben, werden sie üblicherweise als Catch-all-Fallback in SFINAE verwendet.

Innerhalb des Körpers einer Funktion, die variadische Argumente verwendet, können die Werte dieser Argumente mithilfe der <cstdarg> Bibliotheksfunktionen zugegriffen werden.

Definiert im Header <cstdarg>
ermöglicht den Zugriff auf variadische Funktionsargumente
(Funktionsmakro) [bearbeiten]
greift auf das nächste variadische Funktionsargument zu
(Funktionsmakro) [bearbeiten]
(C++11)
erstellt eine Kopie der variadischen Funktionsargumente
(Funktionsmakro) [bearbeiten]
beendet die Durchquerung der variadischen Funktionsargumente
(Funktionsmakro) [bearbeiten]
hält die von va_start, va_arg, va_end und va_copy benötigten Informationen
(typedef) [bearbeiten]

Das Verhalten des Makros va_start ist undefiniert, wenn der letzte Parameter vor dem Auslassungszeichen einen Referenztyp hat oder einen Typ hat, der nicht mit dem Typ, der sich aus Standard-Argument-Promotions ergibt, kompatibel ist.

Wenn eine Paketexpansion oder eine Entität, die aus einer Lambda-Erfassung resultiert, als letzter Parameter in va_start verwendet wird, ist das Programm ill-formed, keine Diagnose erforderlich.

(seit C++11)

[bearbeiten] Alternativen

  • Variadische Templates können auch verwendet werden, um Funktionen zu erstellen, die eine variable Anzahl von Argumenten entgegennehmen. Sie sind oft die bessere Wahl, da sie keine Einschränkungen für die Typen der Argumente auferlegen, keine Ganzzahl- und Gleitkomma-Promotionen durchführen und typsicher sind.
  • Wenn alle variablen Argumente einen gemeinsamen Typ teilen, bietet eine std::initializer_list einen bequemen Mechanismus (wenn auch mit anderer Syntax) für den Zugriff auf variable Argumente. In diesem Fall können die Argumente jedoch nicht geändert werden, da std::initializer_list nur einen konstanten Zeiger auf seine Elemente liefern kann.
(seit C++11)

[bearbeiten] Hinweise

In der Programmiersprache C bis C23 muss mindestens ein benannter Parameter vor dem Auslassungsparameter erscheinen, daher ist R printz(...); bis C23 nicht gültig. In C++ ist diese Form erlaubt, obwohl die an eine solche Funktion übergebenen Argumente nicht zugänglich sind, und wird üblicherweise als Fallback-Überladung in SFINAE verwendet, wobei die niedrigste Priorität der Auslassungskonvertierung in der Überladungsauflösung ausgenutzt wird.

Diese Syntax für variadische Argumente wurde 1983 in C++ ohne das Komma vor dem Auslassungszeichen eingeführt. Als C89 die Funktionsprototypen von C++ übernahm, ersetzte es die Syntax durch eine, die das Komma erforderte. Aus Kompatibilitätsgründen akzeptiert C++98 sowohl den C++-Stil f(int n...) als auch den C-Stil f(int n, ...). Die ursprüngliche C++-Stil-Grammatik ist seit C++26 veraltet.

Das Komma kann in abgekürzten Funktion-Vorlagen verwendet werden, um das Auslassungszeichen für eine variadische Funktion anstelle einer variadischen Vorlage zu kennzeichnen.

void f1(auto...);   // dasselbe wie template<class... Ts> void f3(Ts...)
void f2(auto, ...); // dasselbe wie template<class T> void f3(T, ...)

(seit C++20)

[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 506 C++98 Übergabe von Nicht-POD-Klassenargumenten an einen
Auslassungspunkt führte zu undefiniertem Verhalten
Übergabe solcher Argumente ist
bedingt unterstützt mit
implementierungsdefinierten Semantiken
CWG 634 C++98 bedingt unterstützte Klassentypen
führten dazu, dass einige SFINAE-Idiome nicht funktionierten
immer unterstützt, wenn nicht ausgewertet
CWG 2247 C++11 keine Einschränkung bei der Übergabe von Parameter
Paket oder Lambda-Erfassung an va_start
machte ill-formed,
keine Diagnose erforderlich
CWG 2347 C++11 Es war unklar, ob Scoped-Aufzählungen übergeben werden
an einen Auslassungspunkt sind Standard-Argument-Promotions unterworfen
Übergabe von Scoped-Aufzählungen
ist bedingt unterstützt mit
implementierungsdefinierten Semantiken

[bearbeiten] Siehe auch

C-Dokumentation für Variadische Argumente
C-Dokumentation für Implizite Konvertierungen