Ich verwende Microsoft Visual Studio Community 2019, V16.5.2. Ich möchte die Listeninitialisierung testen
Bitte beachten Sie das folgende Testprogramm:
#include <string>
void foo(std::string str) {}
int main() {
foo( {"str1", "str2"} );
return 0;
}
Dies wird ohne Fehler und Warnung kompiliert. Warum?
Es gibt einen Laufzeitfehler: Expression: Transposed pointer range
Kann jemand bitte erklären, was hier passiert?
Bearbeiten.
Ich habe den Code zerlegt und im Debugger ausgeführt
foo( {"str1", "str2"} );
00F739A8 sub esp,1Ch
00F739AB mov esi,esp
00F739AD mov dword ptr [ebp-0C8h],esp
00F739B3 lea ecx,[ebp-0D1h]
00F739B9 call std::allocator<char>::allocator<char> (0F7136Bh)
00F739BE push eax
00F739BF push offset string "str2" (0F84DB8h)
00F739C4 push offset string "str1" (0F84E2Ch)
00F739C9 mov ecx,esi
00F739CB call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> ><char const *,0> (0F71569h)
00F739D0 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (0F71843h)
00F739D5 add esp,1Ch
Es stürzt beim ersten Aufruf des Konstruktors ab?
Antworten:
std::string
hat einen Vorlagenkonstruktor, der eine Zeichenfolge aus einem Anfang / Ende-Iteratorpaar erstellt. String-Literale in C ++ gehen aufconst char*
s . Und Zeiger sind Iteratoren. Daher hat die Listeninitialisierung den Anfang / Ende-Paarkonstruktor ausgewählt.Sie haben einen Laufzeitfehler erhalten, weil die beiden Zeiger keinen gültigen Bereich erstellen, der (im Allgemeinen) zur Kompilierungszeit nicht ermittelt werden kann.
quelle
<char const *,0>
. Kann das bitte jemand erklären?template< InputIt > (InputIt first, InputIt last,...)
Konstruktor auf, in dem sich der Vorlagenparameteriter
befindetconst char*
... und anscheinend hat Ihre Implementierung aus irgendeinem Grund einen zweiten ganzzahligen Parameter?std::string
hat eine Konstruktorüberladung in Form vonund dies wird aufgerufen, weil
"str1"
und"str2"
zerfällt zuconst char*
's undconst char*
ist ein akzeptabler Iteratortyp.Sie erhalten einen Absturz, weil der "Iteratorbereich", den Sie an die Funktion übergeben haben, ungültig ist.
quelle
Diese verwenden den Konstruktor mit Iteratoren von std :: string (6.).
Mit [
InputIt
=const char*
].Dann haben Sie UB, da der Bereich
{"str1", "str2"}
ungültig ist.quelle