2012-11-16 13 views
8

Manchmal, wenn ich in C++ programmieren möchte ich wünschte, es gäbe einen undefined Wert für jede Variable so etwas wie Javascript !. Zum Beispiel, wenn ich einen Wert für out-of-bounds Element eines Arrays zurückkehrte, war es sinnvoll, eine undefined statt werfen eine Ausnahme zurückzukehren, oder:Eine ungültige Referenz zurückgeben

template <typename T, int SIZE> 
class MyArray 
{ 
    T arr[SIZE]; 
    static T badref; 
public: 
    T &operator[](int i) 
    { 
    if (i >=0 && i < SIZE) 
     return arr[i]; 
    else 
     throw std::string("OUT-OF-BOUNDS"); // or: return badref; !! 
    } 
}; 

Ein weiteres schmutziges (meiner Meinung nach) Die Option gibt eine Referenz einer vordefinierten Variable als ungültige Referenzvariable zurück. Ich weiß, dass wir null oder etwas Ähnliches zu einer Referenzvariablen nicht zuweisen können.

Gibt es ein weiteres wohlgeformtes Muster, um eine Referenz zurückzugeben, bei der der Aufrufer den zurückgegebenen Wert herausfinden kann?

EDIT: Ich meine nicht ein pointer

+5

Ja, es heißt ein Zeiger. Alternativ, 'boost :: optional. – chris

+2

Machen Sie Ihr badref-Objekt mindestens so, dass es statisch ist, dann wird es in keinem MyArray, das Sie erstellen, Speicherplatz einnehmen. Aber ich stimme zu, es ist hässlich. In generischem Code wie diesem würde ich eher eine Ausnahme werfen – john

+0

@john: Ja, ich habe es bearbeitet. – deepmax

Antwort

5

Sie Boost verwenden können :: optional als @ Chris in seinem Kommentar erwähnt. Es kommt als Teil der Boost-Bibliothek. Weitere Informationen finden Sie unter this page.

Modified Klasse:

template <typename T, int SIZE> 
class MyArray 
{ 
    T arr[SIZE]; 
public: 
    optional<T&> operator[](int i) 
    { 
    if (i >=0 && i < SIZE) 
     return optional<T&>(arr[i]); 
    else 
     return optional<T&>(); 
    } 
}; 

Verbrauch:

MyArray<int>() array; 
// fill array with data 

optional<int&> result = array[0]; 
if (result) { 
    // item was found 
} else { 
    // index out of bounds 
} 
+0

Was für badref? –

+0

@DenisErmolin Ich persönlich bevorzuge boost :: optional, da es explizit besagt, dass der Rückgabewert von operator [] nicht definiert sein könnte und Sie sollten auf diese Bedingung überprüfen. –

+0

@MasoudM. Ich habe meine Antwort bearbeitet und einen Link für die Dokumentation hinzugefügt. Sie können mehr über Boost hier erfahren: http://www.boost.org/doc/libs/1_52_0/index.html –

2

Was auch immer Sie denken, Ihre Lösung muss in der Art System passen. Also muss Ihre Funktionssignatur explizit (auf die eine oder andere Weise) sagen, dass das Ergebnis T sein kann, aber es kann auch etwas anderes sein.

Gängige Methoden dafür sind:

  • Anstatt einen Wert zurückzugeben, kehren einen Statuscode und Ausgabe der Wert über ein „out“ Parameter (ein Zeiger oder Referenz):

    bool tryGet(int i, T& result); 
    
  • Return ein Tupel (Status, Wert) wie:

    std::tuple<bool, T> get(int i) 
    

    (Wenn c ouldn't erhalten, sollten Sie die zweite Tupelelement irrelevant - erfordert T einen Standardkonstruktor haben)

  • Verwendung boost::variant (flexibel, aber erfordert Boost)

  • Verwenden boost::optional (einfachere Version des oben, wenn Sie nur müssen „entweder T oder nichts“)
3

ich wünschte, es ein nicht definierter Wert für jede Variable so etwas wie Javascript war!

Sie haben nur einen "undefinierten" Wert für Zeiger (nullptr). Eine Referenz ist (definitionsgemäß) etwas, das auf eine Instanz zeigt, die auf eine gültige Instanz verweist.

Um einen Verweis auf ein statisches Objekt zurückgeben, können Sie zwischen const und nicht konstanten Werten des Betreibers trennen sollten:

template <typename T, int SIZE> 
class MyArray 
{ 
    T arr[SIZE]; 
    static T badref; 
public: 
    T &operator[](int i) 
    { 
    if (i >=0 && i < SIZE) 
     return arr[i]; 
    else 
     // returning ref here would allow clients to write: 
     // MyArray<int> a; 
     // a[-1] = 5; // valid if you return a non-const reference 
     throw std::string("OUT-OF-BOUNDS"); 
    } 
    const T &operator[](int i) const 
    { 
    if (i >=0 && i < SIZE) 
     return arr[i]; 
    else { 
     // MyArray<int> a; 
     // a[-1] = 5; // will not compile (cannot assign to const) 
     static const T invalid = T(); 
     return invalid; 
    } 
    } 

};

0

Das Hauptziel von Referenzen besteht darin, ungültige (NULL) Werte zu vermeiden, während Funktionen ihre Argumente ändern und keine Daten kopieren dürfen. Wenn Sie einen NULL-Wert benötigen, verwenden Sie einen Zeiger.

Verwandte Themen