Ein Mitarbeiter wollte dies schreiben:
std::string_view strip_whitespace(std::string_view sv);
std::string line = "hello ";
line = strip_whitespace(line);
Ich sagte, dass die Rückkehr string_view
mich a priori unruhig machte , und außerdem sah das Aliasing hier für mich wie UB aus.
Ich kann mit Sicherheit sagen, dass line = strip_whitespace(line)
in diesem Fall gleichbedeutend ist mit line = std::string_view(line.data(), 5)
. Ich glaube, das wird rufen string::operator=(const T&) [with T=string_view]
, was als äquivalent line.assign(const T&) [with T=string_view]
definiert ist, was als äquivalent line.assign(line.data(), 5)
definiert ist, was definiert ist, um dies zu tun:
Preconditions: [s, s + n) is a valid range.
Effects: Replaces the string controlled by *this with a copy of the range [s, s + n).
Returns: *this.
Dies sagt jedoch nicht aus, was passiert, wenn Aliasing stattfindet.
Ich habe diese Frage gestern auf dem cpplang Slack gestellt und gemischte Antworten bekommen. Suchen Sie hier nach super maßgeblichen Antworten und / oder empirischen Analysen der Implementierungen realer Bibliotheksanbieter.
Ich schrieb Testfälle für string::assign
, vector::assign
, deque::assign
, list::assign
, und forward_list::assign
.
- Mit Libc ++ funktionieren alle diese Testfälle.
- Mit Libstdc ++ funktionieren alle außer
forward_list
den Segfaults. - Ich weiß nichts über die Bibliothek von MSVC.
Der Segfault in libstdc ++ gibt mir Hoffnung, dass dies UB ist; Ich sehe aber auch, dass sowohl libc ++ als auch libstdc ++ große Anstrengungen unternehmen, damit dies zumindest in den üblichen Fällen funktioniert.
quelle
*this
. Ich sehe jedoch nichts, was die Wiederverwendung des vorhandenen Speichers verhindern könnte. In diesem Fall wird dies nicht angegeben, da die Semantik des Kopierens des Speichers nicht angegeben ist.std::string::assign
Fall und für den Containerfall (std::vector::assign
speziell) .assign
Anforderungen in [tab: container.seq.req] vorbedingt verletzt wurden .Antworten:
Abgesehen von einigen Ausnahmen, von denen Ihre keine ist, macht das Aufrufen einer Nicht-Konstanten-Mitgliedsfunktion (dh
assign
) für eine Zeichenfolge [...] Zeiger [...] auf ihre Elemente ungültig . Dies verstößt gegen die Voraussetzung auf ,assign
dass[s, s + n)
ein gültiger Bereich, so dass diese nicht definiertes Verhalten ist.Beachten Sie, dass
string::operator=(string const&)
die Sprache speziell dafür vorgesehen ist, die Selbstzuweisung zu einem No-Op zu machen.quelle
assign
? Wenn ja, müssten wir einen bestimmten Punkt in der Implementierung von assign festlegen, um zu markieren, wann genau die Ungültigmachung auftreten kann, und ich glaube, dass C ++ dies nicht tun würde. Ich könnte mich jedoch irren.std::vector::insert(iterator pos, const T& value)
funktionieren muss, wennvalue
es sich um den Vektor selbst handelt, da der Standard dies nicht spezifiziert darf nicht funktionieren, obwohl diese Referenz durch den Aufruf möglicherweise ungültig wird.