2009-03-01 10 views
0

Ich habe einen Vektor, den ich mit einer bekannten Menge von Elementen (N) geladen habe.Vektor Größenanpassung - portable Art zu erkennen

Die Verarbeitung erstellt dynamisch neue Elemente, die an den Vektor angehängt werden.

Ich erwarte etwa 2 * N zusätzliche Elemente erstellt werden, so die Größe ich den Vektor 3 * N.

Wenn die zusätzlichen Elemente übersteigen, würde ich ein Programm wie abbrechen, anstatt eine dynamische Expansion des Vektors.

Gibt es eine Möglichkeit, das zu erkennen, das ist tragbar zwischen AIX/TRU64/Linux?

Antwort

3

Was erkennen? Ob der Vektor in der Größe geändert wird? Ob es gewesen ist?

Die einzige Möglichkeit, dies zu erreichen, besteht darin, die Überprüfungsfunktionalität entweder in einem benutzerdefinierten Zuordner oder in einer Funktion bereitzustellen, die dem Vektor Elemente hinzufügt.

beispiel

template<class T> 
void add_element(std::vector<T>& container, T const& v) 
{ 
    if (container.capacity()+1 >= 3*N) 
    { 
    // terminate/exception/whatever 
    } 

container.push_back(v); 
} 
2

Ihre eigene Klasse erstellen, die auf den Vektor übertragen werden. Und überprüfen Sie die Größe in Ihrem eigenen Pushback.

2

Wenn Sie die Größe zur Kompilierzeit kennen, wäre vielleicht die Verwendung eines std :: tr1 :: array (oder boost::array) eine bessere Wahl. Es behält eine feste Größe und überprüft den Zugriff wie std :: vector.

Wenn Sie es jedoch nur zur Laufzeit wissen, wie hier bereits erwähnt, sollten Sie Ihren Vektor in einer Klasse mit bestimmten Funktionen kapseln, die die gewünschten Bedingungen überprüfen (z. B. über Assertions).

In diesem letzten Ansatz würde ich vorschlagen, wenn Sie die maximale Größe bei der Vektorerstellung kennen, die maximale Größe des Vektors in Ihrem Kapselungsklassenkonstruktor (std :: vector :: reserve()) zu reservieren (oder Initialisierungsfunktion). Auf diese Weise wird es keine Speichermanipulationen mehr durch den Vektor selbst geben (nur wenn der Vektorelementkonstruktor/-destruktor solche Manipulationen durchführt). Wenn Sie dann eine einfache Assertion hinzufügen, die überprüft, dass sich die Vektorkapazität (std :: vector :: capacity()) am Anfang und am Ende aller Funktionen Ihrer Klasse nicht ändert, können Sie sicherstellen, dass der Speicher nicht verschoben wird.

Zum Beispiel (DATA_MAX_SIZE unter der Annahme ist eine Standard maximale Größe irgendwo definiert):

template< typename MyType > 
class MyData 
{ 
public: 
    MyData(unsigned long max_size = DATA_MAX_SIZE) 
     : m_max_size(max_size) 
     { m_data.reserve(m_max_size); } 

    void add(const MyType& value) { check_capacity(); m_data.push_back(value); check_capacity(); } 



private: 

    std::vector<MyType> m_data; 
    const unsigned long m_max_size; 

    void check_capacity() { if(m_data.capacity() != m_max_size) throw Exception("Useful error message here!"); } 

}; 

Oder so ähnlich ...

3

Warum Sie einen Vektor verwenden? Der gesamte Punkt des Vektors besteht darin, bei Bedarf dynamisch zu expandieren.

Anstatt eine Klasse zu erstellen, die an den Vektor delegiert wird, erstellen Sie einfach eine Klasse, die an ein einfaches Array delegiert werden soll. Lassen Sie Ihre Push_back die Größe überprüfen und bei Bedarf abbrechen.

2

Std-Klassen verwenden einen Zuordner, der jedes Mal aufgerufen wird, wenn Sie ein Element einfügen. Sie können einen neuen Zuordner schreiben, der von std :: alocator erbt, und alle erforderlichen Überprüfungen/Abhängigkeiten hinzufügen.

(Ich habe das vorher gemacht, aber es hat eine Weile gedauert, bis ich funktionierenden Code erstellt habe.)

+1

Der Zuordner wird nicht unbedingt jedes Mal aufgerufen, der Vektor wird ihn nur verwenden, wenn er die Kapazität erhöhen muss, nicht die Größe –

Verwandte Themen