2010-11-15 3 views
11

Bedenken Sie:Darf std :: vector :: push_back aus einem anderen Grund als der fehlgeschlagenen Neuzuweisung oder Konstruktion ausgelöst werden?

std::vector<int> v; 
v.reserve(1); 
v.push_back(1); // is this statement guaranteed not to throw? 

ich int entschieden, weil es keine Konstrukteuren hat, die werfen könnte - natürlich aus, wenn einige Copykonstruktor von T, so dass Ausnahme entkommt vector<T>::push_back.

Diese Frage gilt sowohl für insert als push_back, aber es wurde von Is it safe to push_back 'dynamically allocated object' to vector? inspiriert, die push_back fragen geschieht.

In den C++ 03 und C++ 0x Standard/FCD, die Beschreibungen von vector::insert sagen, dass Iteratoren/Referenzen vor dem Einfügepunkt gültig bleiben, wenn keine Neuzuordnung auftritt. Sie nicht sagen, dass, wenn keine Neuzuweisung passiert, keine Ausnahme ausgelöst wird (es sei denn von Konstruktoren usw. von T).

Gibt es sonst noch etwas im Standard, um dies zu garantieren?

Ich erwarte nicht push_back alles zu tun, die in diesem Fall werfen könnte. Die GNU-Implementierung tut dies nicht. Die Frage ist, ob der Standard dies verbietet.

Als Follow-up, kann jemand einen Grund denken, warum jede Implementierung werfen würde? Das beste, was ich mir vorstellen kann, ist, dass, wenn ein Anruf bei reserve die Kapazität auf einen Wert von über max_size() erhöht, dann insert vielleicht erlaubt ist, length_error zu werfen, wenn die maximale Größe überschritten würde. Es wäre nutzlos, die Kapazität über max_size() hinaus zu erhöhen, aber ich sehe nicht sofort etwas verbieten, entweder [Edit: Ihr Allokator würde wahrscheinlich Sie erhöhen Kapazität über max_size, so dass dieser Vorschlag nicht gut sein.]

+1

Ausschließen von Kopierkonstruktoren, die während push_back werfen könnten? – Flexo

+0

@awoodland: Steve benutzt speziell 'int', um das vom Tisch zu nehmen –

+0

@awoodland: ja, und wie John sagt, habe ich ein konkretes Beispiel gewählt, das alles aus Gründen der Einfachheit ignoriert. –

Antwort

1

Nun , hängt es von dem Zuordner ab, den Sie verwenden.

Abgesehen von dem Allokator ist das einzige, worauf Sie sich verlassen können, dass push_back() und push_front() garantiert noop sind, wenn eine Ausnahme ausgelöst wird (23.1-10). Der Standard verbietet definitiv nicht die push_back() Ausnahmen zu werfen.

+0

@Let_Me_Be: hängt in welcher Weise vom Zuordner ab? Haben Sie tatsächlich gesagt, dass 'push_back' (und vermutlich jede andere Funktion eines Containers) beliebige Aufrufe an den Allokator auslösen kann, der auch dann werfen könnte, wenn er nicht neu zugeordnet wird? Ich nehme an, dass ich möglicherweise über "Alloc :: construct" anstatt über Konstruktoren von T sprechen sollte, aber ich denke, ein Zuweiser, der "construct" einwirft, wenn der relevante Konstruktor von T nicht würde, verletzt sowieso den Standard. Es ist mir egal, was in nicht-konformen Programmen passiert :-) –

+0

@Steve Nun, der Standard spricht ausdrücklich darüber, dass insert/push_back noops sind, wenn eine Ausnahme ausgelöst wird (anders als im Konstruktor oder in der Zuweisung von T). Auf der anderen Seite sollte die Neuzuweisung nur erfolgen, wenn die neue Größe größer als die alte Kapazität ist. Es macht keinen Sinn, etwas zu werfen, aber es ist natürlich erlaubt. –

+0

Das ist auch mein Gedanke, es ist erlaubt durch diese Klauseln über Einfügen. Das einzige, was es vielleicht verbieten könnte, sind die anderen 781 Seiten des Standards ;-) Zum Beispiel, ob es eine allgemeine Aussage darüber gab, wann Vektoren werfen können. Ich erwarte sicherlich keine allgemeine Aussage über Container oder Sequenzen, da 'deque' und' list' keine Kapazität haben, also muss 'push_back' für sie immer Speicher reservieren dürfen. –

Verwandte Themen