2016-07-18 8 views
2

Ich habe eine Funktion, die einen Wert zurückgibt, aber unter bestimmten Bedingungen (der Funktion bekannt, aber nicht der Aufrufer) möchte ich den Aufrufer den Wert ignorieren.C++ Funktionen, die ihren Rückgabewert angeben, sollten ignoriert werden

Zum Beispiel sagen Sie, dass Sie die durchschnittliche Meerestemperatur berechnen möchten. Dazu teilen Sie die Erde in eine Million Parzellen und fragen jedes Paket nach seiner Temperatur. Wenn das Paket jedoch an Land liegt, muss der Rückgabewert angeben, dass dieser Wert nicht im Durchschnitt enthalten sein sollte.

Ich kann von ein paar Möglichkeiten denken, diese Arbeit zu machen, aber ich bin nicht sicher, was eine gute Lösung ist:

  1. definieren gefälschte Wert (sagen wir -inf), die nie eine vernünftige sein Rückgabewert. Der Anrufer prüft, ob der Wert gefälscht ist, bevor er es verwendet.
  2. den Rückgabetyp Augment ein Paar zu sein, wo der erste Teil der Wert und der zweite ein boolescher ist die fälschungs Ness
  3. Return ein Vektor, der einen Wert oder keine Werte hat entweder eine
  4. Werfen anzeigt Ausnahme, wenn der Wert ignoriert werden soll, so dass die aufrufende -Funktion die Ausnahme behandeln kann und weiß, dass der Wert ignoriert werden muss.
  5. Return durch Zeiger und verwenden nullptr, um anzuzeigen, dass der Wert sollte 1

Lösung ignoriert werden scheint, wie es am schnellsten und am einfachsten wäre, zu implementieren, aber auch am ehesten Fehler schwer zu schaffen zu finden, wenn Anrufer verwenden die Funktion, ohne zu prüfen, ob der Wert gültig ist.

Die Lösungen 2 und 3 erfordern einen sehr geringfügig höheren Wert, scheinen aber ein annehmbarer Ansatz zu sein.

Lösung 4 erfordert eine große Anzahl von Ausnahmeaufrufen als einen erwarteten Teil des Programms zu werfen. Ich habe keine Erfahrung mit Ausnahmen wie dieser.

Lösung 5 ist schön in seiner Allgemeinheit (und nullptr fühlt wie der beste Weg, um Nichts anzuzeigen), aber der Verweis auf einen Zeiger, nur um eine Verdoppelung zu bekommen scheint grob ineffizient.

Ich weiß, dass der einzige Weg zu wirklich wissen, welche Lösung am schnellsten ist, sie alle zu testen, aber ich frage mich, ob es irgendwelche gemeinsamen Best Practices sind für Situationen wie diese Handhabung.

Leistung ist relativ wichtig für mich, da diese Funktion etwa 10.000 Mal pro Frame aufgerufen wird.

Es gibt wahrscheinlich Antworten auf Fragen wie diese, aber ich weiß nicht, welche Suchbegriffe dies als "C++ fake/ignore return value" beschreiben, sind anscheinend nicht gut.

+4

ich würde verwenden Option 1. Es ist einfach, leicht durch zukünftige Maintainer verstanden, und etwa so effizient wie Sie gehen zu bekommen. –

+0

das heißt, dies ist eine Meinungsumfrage Frage so zu schließen wählen. –

+0

Einige Compiler implementieren das bald zu Stande sein rd [std :: optional] (http://en.cppreference.com/w/cpp/utility/optional) Klasse. Vielleicht einen Blick wert. – Galik

Antwort

2

Eine einfache und billige Weise, die Sie nicht aufgeführt haben, ist durch Bezugnahme (Ausgangsparameter) weitergeben müssen:

bool averageValue(int &myVal, ...) { 
    // calculate average 
    myVal = average; 
    if (land) { 
     return false; 
    } 
    return true; 
} 

int avgVal; 
if (averageValue(avgVal, ...)) { 
    //add to the total val. 

Dies wegen wird 1 schnellst Option # nicht wahrscheinlich (aber nur die zusätzliche vergleichen) aber es wird sehr sehr nah sein und hat den Vorteil der Code-Klarheit und keine magischen Zahlen.

+3

downvoter, eine Erklärung führt immer zu einer besseren Antwort. –

+0

Die bessere Antwort wäre keine Antwort auf schlechte Fragen. –

3

Dies scheint eine etwas auf die Meinung bezogene Frage zu sein.

Meine Meinung ist, dass der beste Ansatz ist, ein optional<T> Objekt zurückzugeben; Wenn es leer ist, bedeutet dies, dass kein Wert zurückgegeben wird, und wenn es nicht leer ist, muss der Aufrufer es explizit "dereferenzieren", um den Wert zu erhalten, obwohl keine Heap-Zuweisung oder Zeiger tatsächlich beteiligt sind. (Eine Ausnahme wird ausgelöst, wenn der Aufrufer vergisst zu überprüfen und versucht, eine T aus einem leeren optional<T> zu erhalten.) Sie können jetzt boost::optional oder std::optional verwenden, sobald C++ 17 herauskommt.

Dies ist mehr oder weniger Option 2 in Bezug auf die Leistung, aber mit einer besseren Schnittstelle.

+0

http://meta.stackoverflow.com/questions/276572/should-one-advise-on-off-topic-questions –

1

benutzte ich # 2 (mit boost::optional zu tun, aber die jüngsten Erfahrung hat mich gelehrt Option 6 (eine Variante von 4 zu verwenden):

bool isValidCoord(int x, int y); 
Data getData(int x, int y) { 
    assert(isValidCoord(x,y)); 
    ... 
} 

Dies teilt schön und Telefonvorwahl ist sauber:

if(isValidCoord(x, y)) 
    doCalculation(getData(x,y)); 
Verwandte Themen