J'utilise Microsoft Visual Studio Community 2019, V16.5.2. Je veux tester initialisation de la liste
Veuillez consulter le programme de test suivant:
#include <string>
void foo(std::string str) {}
int main() {
foo( {"str1", "str2"} );
return 0;
}
Cela se compile sans erreur et sans avertissement. Pourquoi?
Il donne une erreur d'exécution: Expression: Transposed pointer range
Quelqu'un peut-il expliquer ce qui se passe ici?
Éditer.
J'ai démonté le code et l'ai exécuté dans le débogueur
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
Ça plante au premier appel au constructeur?
Réponses:
std::string
a un constructeur de modèle qui construit une chaîne à partir d'une paire d'itérateurs de début / fin. Les littéraux de chaîne en C ++ reviennent àconst char*
s. Et les pointeurs sont des itérateurs. Par conséquent, l'initialisation de la liste a choisi le constructeur de paire de début / fin.Vous avez obtenu une erreur d'exécution car les deux pointeurs ne créent pas réellement une plage valide, qui ne peut pas être déterminée au moment de la compilation (généralement).
la source
<char const *,0>
. Quelqu'un peut-il expliquer cela?template< InputIt > (InputIt first, InputIt last,...)
constructeur où le paramètre de modèleiter
estconst char*
.... et apparemment, votre implémentation a un deuxième paramètre entier pour une raison quelconque?std::string
a une surcharge de constructeur sous la forme deet cela s'appelle parce que
"str1"
et"str2"
pourrirconst char*
etconst char*
est un type d'itérateur acceptable.Vous obtenez un plantage car la "plage d'itérateurs" que vous avez transmise à la fonction n'est pas valide.
la source
Cela utilise le constructeur avec les itérateurs de std :: string (6.).
Avec [
InputIt
=const char*
].Ensuite, vous avez UB car la plage
{"str1", "str2"}
n'est pas valide.la source