8Erklären Sie die Stufen der Exception Safety und wie noexcept Move-Operationen, Container und Codegenerierung beeinflusst.
Exception-Safety-Stufen beschreiben, was gilt, wenn eine Operation wirft. Die basic guarantee bedeutet, dass Invarianten erhalten bleiben und Ressourcen nicht leaken, der Zustand sich aber geändert haben kann. Die strong guarantee bedeutet Commit-oder-Rollback-Semantik: bei Fehlschlag ist der beobachtbare Zustand unverändert. Die nothrow guarantee bedeutet, dass die Operation nicht wirft. Übliche Techniken sind RAII, Arbeit auf Temporaries, Copy-and-Swap und die Anordnung von Mutationen so, dass der Commit erst nach erfolgreicher werfender Arbeit erfolgt. `noexcept` ist ein Vertrag: wirft eine `noexcept`-Funktion, wird `std::terminate` aufgerufen. Es beeinflusst auch generischen Code und Container: etwa kann `std::vector` bei Reallocation Elemente verschieben, wenn der Move-Konstruktor `noexcept` ist; andernfalls wird oft kopiert, häufig über `std::move_if_noexcept`, um Exception-Garantien zu erhalten. `noexcept` kann auch Codegenerierung oder Optimierung erleichtern, indem benötigte Exception-Propagationspfade reduziert werden – aber nur, wenn das Versprechen korrekt ist.
std::vector<T> v;
// During reallocation, an implementation may effectively do:
T* dest = allocate(new_cap);
for (T& x : old_storage) {
construct(dest++, std::move_if_noexcept(x));
}
Diese Frage mit einem KI-Coach beantworten
9Erklären Sie std::expected oder vergleichbare Ergebnistypen als Alternative zu Ausnahmen für Operationen, die fehlschlagen können.
std::expected<T,E> enthält entweder einen Erfolgswert T oder einen expliziten Fehler E. Fehler werden Teil des Rückgabetyps statt implizit per Ausnahme weitergegeben. Das eignet sich bei erwartbaren, lokal zu behandelnden Fehlern, etwa Parsing, Validierung, Netzwerkaufrufen, Speicherabfragen und wiederholbaren Backend-Operationen. E sollte strukturierte Angaben wie Code, Kategorie, Wiederholbarkeit, Nachricht oder Zuordnung zu HTTP oder entfernten Prozeduraufrufen (RPC) tragen. Solche Typen lassen sich durch explizite Prüfung und Weitergabe komponieren. Programmierschnittstellen (APIs) im Stil von C++23 können and_then, transform und or_else nutzen, um Schritte ohne tiefe Verschachtelung zu verketten. Gegenüber Ausnahmen werden Kontrollfluss und API-Vertrag sichtbar, auch in Entwürfen ohne Weitergabe von Ausnahmen. std::expected ist selbst aber weder eine portable binäre C-Schnittstelle (ABI) noch eine über verschiedene Entwicklungswerkzeugketten hinweg stabile ABI. Definieren Sie für solche Grenzen eine feste Darstellung. Enthaltene Operationen oder value() im Fehlerfall können weiterhin Ausnahmen auslösen. Für seltene, nicht lokale oder tatsächlich außergewöhnliche Fehler können Ausnahmen je nach Projektrichtlinie angemessen bleiben.
enum class Errc { BadRequest, NotFound, Timeout, DbUnavailable };
struct Error {
Errc code;
bool retryable;
std::string message;
};
std::expected<User, Error> load_user(UserId id);
HttpResponse handle(UserId id) {
auto user = load_user(id);
if (!user) {
switch (user.error().code) {
case Errc::BadRequest: return {400, user.error().message};
case Errc::NotFound: return {404, "not found"};
case Errc::Timeout: return {503, "try again"};
case Errc::DbUnavailable: return {503, "service unavailable"};
}
}
return {200, serialize(*user)};
}
Diese Frage mit einem KI-Coach beantworten