2016-03-28 8 views
6

Ich habe eine operator[] für meine Klasse und alles, was es tut, ist auf einem unique_ptr Mitglied anrufen. Der relevante Teil ist gerade dies:Unter welchen Umständen könnte std :: unique_ptr :: operator [] werfen?

template <typename T> struct Foo { 
    T& operator [](const size_t pos) const noexcept 
    { 
     return data_[pos]; 
    } 

    std::unique_ptr<T[]> data_; 
}; 

ich den Bediener als noexcept markiert haben. Jedoch ist unique_ptr::operator[]nichtnoexcept. Ich kann nicht herausfinden, warum das so ist, und ob ich nur annehmen kann, dass es nie werfen wird. unique_ptr::operator[] selbst listet keine Ausnahmen in der Dokumentation (cppreference und MSDN behaupten, es keine Liste der Ausnahmen zu definieren, die es werfen könnte.)

Also ich nehme an, die fehlende noexcept könnte entweder sein: a) ein Fehler, oder b) der zugrundeliegende Datentyp, auf den der Operator zugreift, wird möglicherweise ausgelöst. Option a wäre nett, denn das würde bedeuten, dass ich meinen eigenen Operator noexcept markieren kann. Option b wäre schwer zu verstehen, da der Operator eine Referenz erhält und nichts anruft.

Also, lange Geschichte kurz, gibt es eine Möglichkeit von unique_ptr::operator[] jemals werfen, und ist es sicher, es von einer noexcept Funktion zu nennen?

+1

Nun 'unique_ptr :: operato []' wendet nur 'operator []' auf den zugrunde liegenden Zeiger an, richtig? Das kann leicht zu undefiniertem Verhalten führen, wenn der Index zu groß ist, also wer weiß, was passieren könnte ... – DeiDei

+0

@DeiDei Das wäre UB, aber nicht werfen. – vsoftco

+0

@DeiDei 'unique_ptr' führt keine Bereichsüberprüfung durch (und es fehlt ein' at() '-Member). Wenn der Zugriff außerhalb des Bereichs liegt, wird er nicht ausgelöst. In der Tat, ich denke nicht, dass es sogar die aktuelle Größe im Auge behält, also könnte es nicht prüfen und werfen, selbst wenn es gewünscht wird. –

Antwort

1

So lange Geschichte kurz, gibt es eine Möglichkeit, unique_ptr :: operator [] jemals werfen

Ja. Es wird einfach [] auf den Zeigertyp verwenden, den es hat. Und das könnte werfen. Erinnern Sie sich daran, dass der Zeigertyp dank Löschgymnastik kein tatsächlicher Zeiger sein muss. Es könnte ein benutzerdefinierter Objekttyp mit einer eigenen operator[] Überladung sein, die auf eine Out-of-Bounds-Verwendung hinauslaufen könnte.

1

Ich dachte, ich versuche es (ich bin mir der Antwort nicht sicher).

Ich ging durch die noexcept reference und mein Verständnis ist, dass noexcept einfach anzeigt, dass die Funktion sollte nicht Ausnahme auslösen, so dass der Compiler aggressivere Optimierungen machen könnte. Warum unique_ptr::operator[] ist nicht noexcept I erraten, dass die eine Standardisierung vorgestellt, dass einige Implementatoren werfen können und einige andere möglicherweise nicht. Meine Meinung ist, dass unique_ptr::operator[] möglicherweise abhängig von der Implementierung von unique_ptr (in der Regel, wenn der Index nicht gebunden ist) werfen kann. Abhängig vom Kontext Ihres Codes können Sie jedoch sicherstellen, dass dies nicht geschieht, und entscheiden, noexcept für Ihren Operator [] anzugeben.

+0

"* mein Verständnis ist, dass noexcept nur angibt, dass die Funktion keine Ausnahme auslösen soll *" Wie erhalten Sie dieses Verständnis von diesem Link? Es sagt sehr deutlich: "Wenn eine Suche nach einem passenden Ausnahmebehandler eine Funktion verlässt, die als noexcept oder noexcept (true) markiert ist, wird std :: terminate sofort aufgerufen." Oder, wenn Sie versuchen, eine Ausnahme aus einer 'noexcept'-Funktion zu werfen, wird' std :: terminate' aufgerufen. Das ist kein "sollte nicht"; es ist ein "* kann * nicht". –

+0

@ NicolBolas, ich fand es in den Notizen am Ende der Seite. –

+0

@NicolBolas, sorry mein Mystake, ich dachte das von meinem * sollte * zur Kompilierzeit. –

Verwandte Themen