Sink-Argumente und Verschieben von Semantiken für Funktionen, die fehlschlagen können (starke Ausnahmesicherheit)

9

Ich habe eine Funktion, die auf einem großen Datenblock arbeitet, der als Sink-Argument übergeben wird. Mein BigData -Typ ist bereits C ++ 11-fähig und kommt mit voll funktionsfähigen Move-Konstruktor- und Move-Assignment-Implementierungen, so dass ich wegkommen kann, ohne das verdammte Ding kopieren zu müssen:

%Vor%

Das alles funktioniert einwandfrei. Meine Verarbeitungsfunktion kann jedoch gelegentlich zur Laufzeit fehlschlagen, was zu einer Ausnahme führt. Das ist nicht wirklich ein Problem, da ich einfach Sachen reparieren und wiederholen kann:

%Vor%

Natürlich wird das nicht funktionieren.

Da ich meine Daten in die Verarbeitungsfunktion verschoben habe, wird b nicht mehr verwendbar sein, wenn ich im Ausnahmebehandler angekommen bin.

Das droht meine Begeisterung für die Weitergabe von Sinkargumenten als Wert zu reduzieren.

Hier ist also die Frage: Wie geht es im modernen C ++ - Code mit einer solchen Situation? Wie kann der Zugriff auf Daten abgerufen werden, die zuvor in eine Funktion verschoben wurden, die nicht ausgeführt werden konnte?

Sie können die Implementierung und die Schnittstellen für BigData und processBigData beliebig ändern. Die endgültige Lösung sollte jedoch versuchen, Nachteile gegenüber dem ursprünglichen Code in Bezug auf Effizienz und Benutzerfreundlichkeit zu minimieren.

    
ComicSansMS 04.09.2014, 13:53
quelle

2 Antworten

2

Ich bin in ähnlicher Weise von diesem Problem verblüfft.

Soweit ich das beurteilen kann, besteht das beste aktuelle Idiom darin, den Pass-by-Value in ein Paar von Pass-by-Referenzen aufzuteilen.

%Vor%

Natürlich könnten Teile des Arguments vor der Ausnahme verschoben worden sein. Das Problem wird an alle Aufrufe von processBigData weitergegeben.

Ich hatte eine Inspiration, ein Objekt zu entwickeln, das sich auf bestimmte Ausnahmen zurückverlagert, aber das ist eine Lösung für ein bestimmtes Problem am Horizont in einem meiner Projekte. Es könnte am Ende zu spezialisiert oder gar nicht machbar sein.

    
Potatoswatter 04.09.2014 14:05
quelle
2

Anscheinend wurde dieses Thema auf der letzten CppCon 2014 lebhaft diskutiert. Herb Sutter fasste den letzten Stand der Dinge in seinem Abschlussreferat zusammen: Zurück zu den Grundlagen! Grundlagen des modernen C ++ - Stils (Folien) .

Seine Schlussfolgerung ist ganz einfach: Verwenden Sie keinen Pass-by-Wert für Sink-Argumente.

Die Argumente für die Verwendung dieser Technik an erster Stelle (wie von Eric Niebler's Meeting C ++ 2013 Keynote C ++ 11 Bibliotheksdesign (Folien) ) scheint von den Nachteilen aufgewogen zu werden. Die ursprüngliche Motivation für die Weitergabe von Sinkargumenten als Wert war, die kombinatorische Explosion für Funktionsüberlastungen zu beseitigen, die sich aus der Verwendung von const& / && ergibt.

Leider scheint dies eine Reihe von unbeabsichtigten Konsequenzen zu haben. Eines davon sind potenzielle Effizienznachteile (hauptsächlich aufgrund unnötiger Pufferzuweisungen). Der andere ist das Problem mit Ausnahme Sicherheit von dieser Frage. Beide werden in Herb's Gespräch besprochen.

Herbs Schlussfolgerung ist, nicht Pass-by-Value für Sink-Argumente zu verwenden, sondern stattdessen auf separate const& / && (wobei const& der Standardwert und && reserviert ist) für die wenigen Fälle, in denen eine Optimierung erforderlich ist).

Dies entspricht auch der Antwort von @ Potatowatter . Durch Übergabe des Sink-Arguments über && können wir möglicherweise die tatsächliche Verschiebung der Daten vom Argument auf einen Punkt verschieben, an dem wir keine Garantie geben können.

Mir gefiel die Idee, Sinkargumente nach Wert zu übergeben, aber es scheint, dass es in der Praxis nicht so gut funktioniert, wie alle erhofft haben.

    
ComicSansMS 17.09.2014 12:06
quelle