2016-03-04 2 views
17

Ich weiß von const, das kann nach der Erstellung nicht geändert werden. Aber ich frage mich, ob es eine Möglichkeit gibt, eine Variable zu deklarieren, die Sie nur einmal setzen und danach nicht überschreiben können. In meinem Code möchte ich die bool Variable vermeiden, indem Sie eine nFirst haben, die, einmal auf nIdx gesetzt, nicht auf den neuen Wert von nIdx gesetzt werden kann.Kann eine Variable definiert werden, die nur einmal gesetzt werden kann?

Mein Code:

int nFirst = 0; 
    int nIdx = 0; 
    bool bFound = false; 
    BOOST_FOREACH(Foo* pFoo, aArray) 
    { 
     if (pFoo!= NULL) 
     { 
      pFoo->DoSmth(); 
      if (!bFound) 
      { 
       nFirst= nIdx; 
       bFound = true; 
      } 
     } 
     nIdx++; 
    } 
+5

Keine eingebaut in AFAIK, aber Sie können Ihre eigene Klasse rollen das macht das ganz leicht. –

+0

Nein, das ist mit Standardfunktionen nicht möglich. –

+2

Sie können dafür eine eigene Klasse erstellen. Aber der ursprüngliche boolesche Ansatz ist, was diese Klasse auch verwenden muss, so dass es keinen Unterschied in der Leistung gibt. –

Antwort

11

Ich möchte die Bool Variable

Sie können prüfen, nFirst selbst, basiert auf der Tatsache vermeiden, dass es nicht eine negative Zahl gesetzt werden . Wie zum Beispiel:

int nFirst = -1; 
int nIdx = 0; 
BOOST_FOREACH(Foo* pFoo, aArray) 
{ 
    if (pFoo != NULL) 
    { 
     pFoo->DoSmth(); 
     if (nFirst == -1) 
     { 
      nFirst = nIdx; 
     } 
    } 
    nIdx++; 
} 
+1

@eugenesh jede Variable mit einem ** const ** Präfix kann nicht geändert werden, z. ** const double pi = 3,141592653; ** –

+2

Dies scheint der einfachste Ansatz zu sein und vermeidet den booleschen Wert. Vielen Dank! – tzippy

+0

Sie können auch enum ** enum bool {falsch, wahr} ** ** enum Farbe {rot = 1, blau = 16, grün = 256} ** und Sie können const enum oder typedef enum haben. –

12

Ziemlich einfach, Ihre eigenen zu rollen.

template<typename T> 
class SetOnce 
{ 
public: 
    SetOnce(T init) : m_Val(init) 
    {} 

    SetOnce<T>& operator=(const T& other) 
    { 
     std::call_once(m_OnceFlag, [&]() 
     { 
      m_Val = other; 
     }); 

     return *this; 
    } 

    const T& get() { return m_Val; } 
private: 
    T m_Val; 
    std::once_flag m_OnceFlag; 
}; 

Dann benutzen Sie einfach die Wrapper-Klasse für die Variable.

SetOnce<int> nFirst(0); 
nFirst= 1; 
nFirst= 2; 
nFirst= 3; 

std::cout << nFirst.get() << std::endl; 

Ausgänge:

+1

@ Jarod42 Korrigiert, habe zuerst einen Bool benutzt, um es zu verfolgen. – lcs

0

Ihre Frage bezieht sich auf die Bool zu vermeiden, sondern impliziert auch die Notwendigkeit für const-ness.

die Bool zu vermeiden, ich boost :: optional wie folgt verwenden würde:

const boost::optional<int> nFirst; 
// .. 
if (!nFirst) const_cast<boost::optional<int>&>(nFirst) = nIdx; 
// you can use *nFirst to get the value, any attempt to change it would cause a compile-time error 
:

boost::optional<int> nFirst; 
// .. 
if (!nFirst) nFirst = nIdx; 
// and now you can use *nFirst to get its value 

Dann können Sie logisch (und nicht als wörtliche) const-ness wie dies erzwingen

Die Verwendung von const_cast ist nicht die sicherste Übung, aber in Ihrem speziellen Fall und solange Sie es nur tun, sobald es in Ordnung wäre. Es vereinfacht sowohl Ihren Code als auch Ihre Absichten: Sie wollen eine Konstante, es ist nur so, dass Sie die Initialisierung für ein bisschen verzögern möchten.

Nun, wie songyuanyao vorgeschlagen, könnten Sie direkt ein int anstelle von boost :: optional verwenden, aber das letztere macht Ihre Absicht explizit, so denke ich, es ist besser so. Am Ende des Tages ist das C++, während die Lösung von songyuanyao wirklich ein C-Stil ist.

+3

Ein 'optional' vermeidet nicht wirklich' bool', es versteckt es in einer anderen Klasse. – jxh

+0

Wird 'const_cast' nicht verwendet, um nicht definiertes Verhalten eines konstanten Objekts zu ändern? http://stackoverflow.com/q/14154382 – GingerPlusPlus

0

ähnlich cocarin's, sondern wirft Ausnahme statt still zu ignorieren Zuordnung:

template <typename T, typename Counter = unsigned char> 
class SetOnce { 
public: 
    SetOnce(const T& initval = T(), const Counter& initcount = 1): 
     val(initval), counter(initcount) {} 
    SetOnce(const SetOnce&) = default; 
    SetOnce<T, Counter>& operator=(const T& newval) { 
     if (counter) { 
      --counter; 
      val = newval; 
      return *this; 
     } 
     else throw "Some error"; 
    } 
    operator const T&() const { return val; } // "getter" 
protected: 
    T val; 
    Counter counter; 
}; 

Verbrauch:

SetOnce<int> x = 42; 
std::cout << x << '\n'; // => 42 
x = 4; 
// x = 5; // fails 
std::cout << x << '\n'; // => 4 

Online demo

Verwandte Themen